fix scroll freeze and propagate to built-in scrollers. also genlist now knows
authorCarsten Haitzler <raster@rasterman.com>
Tue, 8 Sep 2009 06:20:32 +0000 (06:20 +0000)
committerCarsten Haitzler <raster@rasterman.com>
Tue, 8 Sep 2009 06:20:32 +0000 (06:20 +0000)
about dragging items. callbacks for that.

SVN revision: 42342

src/bin/test_genlist.c
src/lib/elc_notepad.c
src/lib/elm_genlist.c
src/lib/elm_list.c
src/lib/els_scroller.c

index c6271be..3b3dc31 100644 (file)
@@ -802,6 +802,7 @@ test_genlist5(void *data, Evas_Object *obj, void *event_info)
                                         NULL/* func data */);
 
    elm_box_pack_end(bx, gl);
+   elm_object_scroll_freeze_push(gl);
    evas_object_show(bx2);
 
    bx2 = elm_box_add(win);
index 54da6ad..abf96c4 100644 (file)
@@ -20,7 +20,7 @@ typedef struct _Widget_Data Widget_Data;
 
 struct _Widget_Data
 {
-   Evas_Object *scroller, *entry;
+   Evas_Object *scr, *entry;
    const char *file;
    Elm_Text_Format format;
    Ecore_Timer *delay_write;
@@ -220,6 +220,38 @@ _entry_changed(void *data, Evas_Object *obj, void *event_info)
    wd->delay_write = ecore_timer_add(2.0, _delay_write, data);
 }
 
+static void
+_hold_on(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_scroll_hold_push(wd->scr);
+}
+
+static void
+_hold_off(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_scroll_hold_pop(wd->scr);
+}
+
+static void
+_freeze_on(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_scroll_hold_push(wd->scr);
+}
+
+static void
+_freeze_off(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_scroll_hold_pop(wd->scr);
+}
+
 /**
  * Add a new notepad to the parent
  *
@@ -245,17 +277,22 @@ elm_notepad_add(Evas_Object *parent)
    elm_widget_del_hook_set(obj, _del_hook);
    elm_widget_can_focus_set(obj, 1);
 
-   wd->scroller = elm_scroller_add(parent);
-   elm_widget_resize_object_set(obj, wd->scroller);
+   wd->scr = elm_scroller_add(parent);
+   elm_widget_resize_object_set(obj, wd->scr);
    wd->entry = elm_entry_add(parent);
    evas_object_size_hint_weight_set(wd->entry, 1.0, 1.0);
    evas_object_size_hint_align_set(wd->entry, -1.0, -1.0);
-   elm_scroller_content_set(wd->scroller, wd->entry);
+   elm_scroller_content_set(wd->scr, wd->entry);
    evas_object_show(wd->entry);
 
    elm_entry_entry_set(wd->entry, "");
    evas_object_smart_callback_add(wd->entry, "changed", _entry_changed, obj);
-
+   
+   evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
+   
    wd->auto_write = EINA_TRUE;
 
    _sizing_eval(obj);
index ad9bb99..f4585e2 100644 (file)
  * not use the object pointer from elm_genlist_item_object_get() in a way
  * where it may point to freed objects.
  *
+ * drag,start,up - This is called when the item in the list has been dragged
+ * (not scrolled) up.
+ *
+ * drag,start,down - This is called when the item in the list has been dragged
+ * (not scrolled) down.
+ *
+ * drag,start,left - This is called when the item in the list has been dragged
+ * (not scrolled) left.
+ *
+ * drag,start,right - This is called when the item in the list has been dragged
+ * (not scrolled) right.
+ *
+ * drag,stop - This is called when the item in the list has stopped being
+ * dragged.
+ *
  * Genlist has a fairly large API, mostly because it's relatively complex,
  * trying to be both expansive, powerful and efficient. First we will begin
  * an overview o the theory behind genlist.
@@ -281,6 +296,7 @@ struct _Elm_Genlist_Item
    Eina_List *labels, *icons, *states;
    Eina_List *icon_objs;
    Ecore_Timer *long_timer;
+   Evas_Coord dx, dy;
    
    Elm_Genlist_Item *rel;
    int relcount;
@@ -295,6 +311,8 @@ struct _Elm_Genlist_Item
    Eina_Bool queued : 1;
    Eina_Bool showme : 1;
    Eina_Bool delete_me : 1;
+   Eina_Bool down : 1;
+   Eina_Bool dragging : 1;
 };
 
 struct _Pan
@@ -466,6 +484,7 @@ _mouse_move(void *data, Evas *evas, Evas_Object *obj, void *event_info)
 {
    Elm_Genlist_Item *it = data;
    Evas_Event_Mouse_Move *ev = event_info;
+   Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
      {
        if (!it->wd->on_hold)
@@ -474,6 +493,57 @@ _mouse_move(void *data, Evas *evas, Evas_Object *obj, void *event_info)
             _item_unselect(it);
          }
      }
+   if (!it->down) return;
+   if (it->wd->on_hold) return;
+   if (it->wd->longpressed) return;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   evas_object_geometry_get(obj, &x, &y, NULL, NULL);
+   x = ev->cur.canvas.x - x;
+   y = ev->cur.canvas.y - y;
+   dx = x - it->dx;
+   adx = dx;
+   if (adx < 0) adx = -dx;
+   dy = y - it->dy;
+   ady = dy;
+   if (ady < 0) ady = -dy;
+   minw /= 2;
+   minh /= 2;
+   if ((adx > minw) || (ady > minh))
+     {
+        it->dragging = 1;
+        if (it->long_timer)
+          {
+             ecore_timer_del(it->long_timer);
+             it->long_timer = NULL;
+          }
+        if (!it->wd->wasselected)
+          _item_unselect(it);
+        it->wd->wasselected = 0;
+        if (dy < 0)
+          {
+             if (ady > adx)
+               evas_object_smart_callback_call(it->wd->obj, "drag,start,up", it);
+             else
+               {
+                  if (dx < 0)
+                    evas_object_smart_callback_call(it->wd->obj, "drag,start,left", it);
+                  else
+                    evas_object_smart_callback_call(it->wd->obj, "drag,start,right", it);
+               }
+          }
+        else
+          {
+             if (ady > adx)
+               evas_object_smart_callback_call(it->wd->obj, "drag,start,down", it);
+             else
+               {
+                  if (dx < 0)
+                    evas_object_smart_callback_call(it->wd->obj, "drag,start,left", it);
+                  else
+                    evas_object_smart_callback_call(it->wd->obj, "drag,start,right", it);
+               }
+          }
+     }
 }
 
 static int
@@ -482,6 +552,7 @@ _long_press(void *data)
    Elm_Genlist_Item *it = data;
    it->long_timer = NULL;
    if (it->disabled) return 0;
+   if (it->dragging) return 0;
    it->wd->longpressed = EINA_TRUE;
    evas_object_smart_callback_call(it->wd->obj, "longpressed", it);
    return 0;
@@ -492,7 +563,13 @@ _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info)
 {
    Elm_Genlist_Item *it = data;
    Evas_Event_Mouse_Down *ev = event_info;
+   Evas_Coord x, y;
    if (ev->button != 1) return;
+   it->down = 1;
+   it->dragging  = 0;
+   evas_object_geometry_get(obj, &x, &y, NULL, NULL);
+   it->dx = ev->canvas.x - x;
+   it->dy = ev->canvas.y - y;
    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
    else it->wd->on_hold = EINA_FALSE;
    it->wd->wasselected = it->selected;
@@ -510,6 +587,7 @@ _mouse_up(void *data, Evas *evas, Evas_Object *obj, void *event_info)
    Evas_Event_Mouse_Up *ev = event_info;
    Eina_List *l;
    if (ev->button != 1) return;
+   it->down = 0;
    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
    else it->wd->on_hold = EINA_FALSE;
    if (it->long_timer)
@@ -517,8 +595,14 @@ _mouse_up(void *data, Evas *evas, Evas_Object *obj, void *event_info)
         ecore_timer_del(it->long_timer);
         it->long_timer = NULL;
      }
+   if (it->dragging)
+     {
+        it->dragging = 0;
+        evas_object_smart_callback_call(it->wd->obj, "drag,stop", it);
+     }
    if (it->wd->on_hold)
      {
+        it->wd->longpressed = EINA_FALSE;
        it->wd->on_hold = EINA_FALSE;
        return;
      }
@@ -1050,6 +1134,38 @@ _pan_calculate(Evas_Object *obj)
      }
 }
 
+static void
+_hold_on(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_hold_set(wd->scr, 1);
+}
+
+static void
+_hold_off(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_hold_set(wd->scr, 0);
+}
+
+static void
+_freeze_on(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_freeze_set(wd->scr, 1);
+}
+
+static void
+_freeze_off(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_freeze_set(wd->scr, 0);
+}
+
 /**
  * Add a new Genlist object
  *
@@ -1084,6 +1200,11 @@ elm_genlist_add(Evas_Object *parent)
    wd->obj = obj;
    wd->mode = ELM_LIST_SCROLL;
 
+   evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
+   
    if (!smart)
      {
        static Evas_Smart_Class sc;
index 46e7ebf..463f56d 100644 (file)
@@ -5,7 +5,7 @@ typedef struct _Widget_Data Widget_Data;
 
 struct _Widget_Data
 {
-   Evas_Object *scroller, *box;
+   Evas_Object *scr, *box;
    Eina_List *items;
    Eina_List *selected;
    Elm_List_Mode mode;
@@ -73,8 +73,8 @@ _sizing_eval(Evas_Object *obj)
    Widget_Data *wd = elm_widget_data_get(obj);
    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
 
-   evas_object_size_hint_min_get(wd->scroller, &minw, &minh);
-   evas_object_size_hint_max_get(wd->scroller, &maxw, &maxh);
+   evas_object_size_hint_min_get(wd->scr, &minw, &minh);
+   evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
    evas_object_size_hint_min_set(obj, minw, minh);
    evas_object_size_hint_max_set(obj, maxw, maxh);
 }
@@ -429,12 +429,44 @@ _fix_items(Evas_Object *obj)
    mw = 0; mh = 0;
    evas_object_size_hint_min_get(wd->box, &mw, &mh);
    if (wd->mode == ELM_LIST_LIMIT)
-     elm_scroller_content_min_limit(wd->scroller, 1, 0);
+     elm_scroller_content_min_limit(wd->scr, 1, 0);
    else
-     elm_scroller_content_min_limit(wd->scroller, 0, 0);
+     elm_scroller_content_min_limit(wd->scr, 0, 0);
    _sizing_eval(obj);
 }
 
+static void
+_hold_on(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_scroll_hold_push(wd->scr);
+}
+
+static void
+_hold_off(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_scroll_hold_pop(wd->scr);
+}
+
+static void
+_freeze_on(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_scroll_hold_push(wd->scr);
+}
+
+static void
+_freeze_off(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_scroll_hold_pop(wd->scr);
+}
+
 EAPI Evas_Object *
 elm_list_add(Evas_Object *parent)
 {
@@ -452,22 +484,26 @@ elm_list_add(Evas_Object *parent)
    elm_widget_del_hook_set(obj, _del_hook);
    elm_widget_can_focus_set(obj, 1);
 
-   wd->scroller = elm_scroller_add(parent);
-   elm_widget_resize_object_set(obj, wd->scroller);
+   wd->scr = elm_scroller_add(parent);
+   elm_widget_resize_object_set(obj, wd->scr);
 
-   elm_scroller_bounce_set(wd->scroller, 0, 1);
+   elm_scroller_bounce_set(wd->scr, 0, 1);
 
    wd->box = elm_box_add(parent);
    elm_box_homogenous_set(wd->box, 1);
    evas_object_size_hint_weight_set(wd->box, 1.0, 0.0);
    evas_object_size_hint_align_set(wd->box, -1.0, 0.0);
-   elm_scroller_content_set(wd->scroller, wd->box);
+   elm_scroller_content_set(wd->scr, wd->box);
    evas_object_show(wd->box);
 
    wd->mode = ELM_LIST_SCROLL;
 
    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
-
+   evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
+   
    _sizing_eval(obj);
    return obj;
 }
@@ -555,9 +591,9 @@ elm_list_horizontal_mode_set(Evas_Object *obj, Elm_List_Mode mode)
    if (wd->mode == mode) return;
    wd->mode = mode;
    if (wd->mode == ELM_LIST_LIMIT)
-     elm_scroller_content_min_limit(wd->scroller, 1, 0);
+     elm_scroller_content_min_limit(wd->scr, 1, 0);
    else
-     elm_scroller_content_min_limit(wd->scroller, 0, 0);
+     elm_scroller_content_min_limit(wd->scr, 0, 0);
 }
 
 EAPI void
@@ -621,7 +657,7 @@ elm_list_item_show(Elm_List_Item *it)
    evas_object_geometry_get(it->base, &x, &y, &w, &h);
    x -= bx;
    y -= by;
-   elm_scroller_region_show(wd->scroller, x, y, w, h);
+   elm_scroller_region_show(wd->scr, x, y, w, h);
 }
 
 EAPI void
index be00f33..29e2249 100644 (file)
@@ -305,6 +305,7 @@ _smart_scrollto_x(Smart_Data *sd, double t_in, Evas_Coord pos_x)
    Evas_Coord px, py, x, y, w, h;
    double t;
 
+   if (sd->freeze) return;
    if (t_in <= 0.0)
      {
         elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
@@ -369,6 +370,7 @@ _smart_scrollto_y(Smart_Data *sd, double t_in, Evas_Coord pos_y)
    Evas_Coord px, py, x, y, w, h;
    double t;
 
+   if (sd->freeze) return;
    if (t_in <= 0.0)
      {
         elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
@@ -598,6 +600,7 @@ bounce_eval(Smart_Data *sd)
 {
    Evas_Coord mx, my, px, py, bx, by, b2x, b2y;
 
+   if (sd->freeze) return;
    if ((!sd->bouncemex) && (!sd->bouncemey)) return;
    if (sd->down.now) return; // down bounce while still held down
    if (sd->down.onhold_animator)
@@ -1359,7 +1362,8 @@ _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
                          {
                             vel = sqrt((dx * dx) + (dy * dy)) / at;
                             if ((_elm_config->thumbscroll_friction > 0.0) &&
-                                (vel > _elm_config->thumbscroll_momentum_threshhold))
+                                (vel > _elm_config->thumbscroll_momentum_threshhold) &&
+                                (!sd->freeze))
                               {
                                  sd->down.dx = ((double)dx / at);
                                  sd->down.dy = ((double)dy / at);
@@ -1504,7 +1508,7 @@ _smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info)
                    }
                   if (faildir) sd->down.dir_none = 1;
               }
-             if (!sd->hold)
+             if ((!sd->hold) && (!sd->freeze))
                {
                   if ((sd->down.dragged) ||
                       (((x * x) + (y * y)) >