1. fix box as it didnt hide clipper when it gets empty
authorCarsten Haitzler <raster@rasterman.com>
Fri, 8 May 2009 11:27:32 +0000 (11:27 +0000)
committerCarsten Haitzler <raster@rasterman.com>
Fri, 8 May 2009 11:27:32 +0000 (11:27 +0000)
2. add bouncing at ends for scroller and config for it
3. fix quicklaunch to be cserver-freidnly thanks to its fork tricks
4. add signals to scroller when scrolling and hitting edges
5. pants.

SVN revision: 40549

13 files changed:
src/bin/test.c
src/lib/Elementary.h.in
src/lib/elm_genlist.c
src/lib/elm_list.c
src/lib/elm_main.c
src/lib/elm_priv.h
src/lib/elm_scroller.c
src/lib/elm_toolbar.c
src/lib/els_box.c
src/lib/els_icon.c
src/lib/els_pan.c
src/lib/els_scroller.c
src/lib/els_scroller.h

index bef62b6..f09bec9 100644 (file)
@@ -1130,6 +1130,40 @@ my_anchorblock_anchor(void *data, Evas_Object *obj, void *event_info)
 }
 
 static void
+my_anchorblock_edge_left(void *data, Evas_Object *obj, void *event_info)
+{
+   printf("left\n");
+}
+
+static void
+my_anchorblock_edge_right(void *data, Evas_Object *obj, void *event_info)
+{
+   printf("right\n");
+}
+
+static void
+my_anchorblock_edge_top(void *data, Evas_Object *obj, void *event_info)
+{
+   printf("top\n");
+}
+
+static void
+my_anchorblock_edge_bottom(void *data, Evas_Object *obj, void *event_info)
+{
+   printf("bottom\n");
+}
+
+static void
+my_anchorblock_scroll(void *data, Evas_Object *obj, void *event_info)
+{
+   Evas_Coord x, y, w, h, vw, vh;
+   
+   elm_scroller_region_get(obj, &x, &y, &w, &h);
+   elm_scroller_child_size_get(obj, &vw, &vh);
+   printf("scroll %ix%i +%i+%i in %ix%i\n", w, h, x, y, vw, vh);
+}
+
+static void
 my_bt_17(void *data, Evas_Object *obj, void *event_info)
 {
    Evas_Object *win, *bg, *av, *sc, *bx, *bb, *ic;
@@ -1147,6 +1181,12 @@ my_bt_17(void *data, Evas_Object *obj, void *event_info)
    sc = elm_scroller_add(win);
    evas_object_size_hint_weight_set(sc, 1.0, 1.0);
    elm_win_resize_object_add(win, sc);
+   
+   evas_object_smart_callback_add(sc, "edge_left", my_anchorblock_edge_left, NULL);
+   evas_object_smart_callback_add(sc, "edge_right", my_anchorblock_edge_right, NULL);
+   evas_object_smart_callback_add(sc, "edge_top", my_anchorblock_edge_top, NULL);
+   evas_object_smart_callback_add(sc, "edge_bottom", my_anchorblock_edge_bottom, NULL);
+   evas_object_smart_callback_add(sc, "scroll", my_anchorblock_scroll, NULL);
 
    bx = elm_box_add(win);
    evas_object_size_hint_weight_set(bx, 1.0, 0.0);
@@ -1576,9 +1616,15 @@ my_bt_20(void *data, Evas_Object *obj, void *event_info)
 }
 
 static void
+my_li2_clear(void *data, Evas_Object *obj, void *event_info)
+{
+   elm_list_clear(data);
+}
+
+static void
 my_bt_21(void *data, Evas_Object *obj, void *event_info)
 {
-   Evas_Object *win, *bg, *li, *ic, *ic2, *bx;
+   Evas_Object *win, *bg, *li, *ic, *ic2, *bx, *bx2, *bt;
    char buf[PATH_MAX];
    
    win = elm_win_add(NULL, "list-2", ELM_WIN_BASIC);
@@ -1586,12 +1632,19 @@ my_bt_21(void *data, Evas_Object *obj, void *event_info)
    elm_win_autodel_set(win, 1);
 
    bg = elm_bg_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR);
+   elm_bg_file_set(bg, buf, NULL);
    elm_win_resize_object_add(win, bg);
    evas_object_size_hint_weight_set(bg, 1.0, 1.0);
    evas_object_show(bg);
 
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, 1.0, 1.0);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
    li = elm_list_add(win);
-   elm_win_resize_object_add(win, li);
+   evas_object_size_hint_align_set(li, -1.0, -1.0);
    evas_object_size_hint_weight_set(li, 1.0, 1.0);
    elm_list_horizontal_mode_set(li, ELM_LIST_LIMIT);
    elm_list_multi_select_set(li, 1);
@@ -1618,15 +1671,15 @@ my_bt_21(void *data, Evas_Object *obj, void *event_info)
    elm_icon_scale_set(ic2, 0, 0);
    elm_list_item_append(li, "How", ic, ic2,  NULL, NULL);
    
-   bx = elm_box_add(win);
-   elm_box_horizontal_set(bx, 1);
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
 
    ic = elm_icon_add(win);
    snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
    elm_icon_file_set(ic, buf, NULL);
    elm_icon_scale_set(ic, 0, 0);
    evas_object_size_hint_align_set(ic, 0.5, 0.5);
-   elm_box_pack_end(bx, ic);
+   elm_box_pack_end(bx2, ic);
    evas_object_show(ic);
    
    ic = elm_icon_add(win);
@@ -1634,9 +1687,9 @@ my_bt_21(void *data, Evas_Object *obj, void *event_info)
    elm_icon_file_set(ic, buf, NULL);
    elm_icon_scale_set(ic, 0, 0);
    evas_object_size_hint_align_set(ic, 0.5, 0.0);
-   elm_box_pack_end(bx, ic);
+   elm_box_pack_end(bx2, ic);
    evas_object_show(ic);
-   elm_list_item_append(li, "are", bx, NULL,  NULL, NULL);
+   elm_list_item_append(li, "are", bx2, NULL,  NULL, NULL);
    
    elm_list_item_append(li, "you", NULL, NULL,  NULL, NULL);
    elm_list_item_append(li, "doing", NULL, NULL,  NULL, NULL);
@@ -1653,8 +1706,26 @@ my_bt_21(void *data, Evas_Object *obj, void *event_info)
 
    elm_list_go(li);
    
+   elm_box_pack_end(bx, li);
    evas_object_show(li);
    
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, 1.0, 0.0);
+   evas_object_size_hint_align_set(bx2, -1.0, -1.0);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Clear");
+   evas_object_smart_callback_add(bt, "clicked", my_li2_clear, li);
+   evas_object_size_hint_align_set(bt, -1.0, -1.0);
+   evas_object_size_hint_weight_set(bt, 1.0, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
    evas_object_resize(win, 320, 300);
    evas_object_show(win);
 }
@@ -2216,6 +2287,7 @@ my_bt_30(void *data, Evas_Object *obj, void *event_info)
 {
    Evas_Object *win, *bg, *gl, *bx, *bx2, *bt;
    Elm_Genlist_Item *gli[10];
+   char buf[PATH_MAX];
    int i;
    
    win = elm_win_add(NULL, "genlist-2", ELM_WIN_BASIC);
@@ -2223,6 +2295,8 @@ my_bt_30(void *data, Evas_Object *obj, void *event_info)
    elm_win_autodel_set(win, 1);
 
    bg = elm_bg_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR);
+   elm_bg_file_set(bg, buf, NULL);
    elm_win_resize_object_add(win, bg);
    evas_object_size_hint_weight_set(bg, 1.0, 1.0);
    evas_object_show(bg);
index c417520..4ce4877 100644 (file)
@@ -337,7 +337,14 @@ extern "C" {
    EAPI void         elm_scroller_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
    EAPI void         elm_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v);
    EAPI void         elm_scroller_region_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
+   EAPI void         elm_scroller_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
+   EAPI void         elm_scroller_bounce_set(Evas_Object *obj, Evas_Bool h_bounce, Evas_Bool v_bounce);
    /* smart callbacks called:
+    * "edge_left"
+    * "edge_right"
+    * "edge_top"
+    * "edge_bottom"
+    * "scroll"
     */
 
    EAPI Evas_Object *elm_label_add(Evas_Object *parent);
index 0d1cf7d..a016d44 100644 (file)
@@ -623,10 +623,10 @@ _pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
    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 < 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;
@@ -751,6 +751,8 @@ elm_genlist_add(Evas_Object *parent)
    wd->scr = elm_smart_scroller_add(e);
    elm_widget_resize_object_set(obj, wd->scr);
    
+   elm_smart_scroller_bounce_allow_set(wd->scr, 0, 1);
+   
    wd->obj = obj;
    wd->mode = ELM_LIST_SCROLL;
    
index b00e33d..92a974e 100644 (file)
@@ -370,6 +370,8 @@ elm_list_add(Evas_Object *parent)
    wd->scroller = elm_scroller_add(parent);
    elm_widget_resize_object_set(obj, wd->scroller);
    
+   elm_scroller_bounce_set(wd->scroller, 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);
index b98b427..a5a57bb 100644 (file)
@@ -91,6 +91,8 @@ elm_shutdown(void)
 static const char *elm_engine, *elm_scale, *elm_theme, *elm_prefix, *elm_data_dir;
 static const char *elm_font_hinting, *elm_font_path, *elm_image_cache;
 static const char *elm_font_cache, *elm_finger_size, *elm_fps;
+static const char *elm_thumbscroll_enabled, *elm_thumbscroll_threshhold;
+static const char *elm_thumbscroll_momentum_threshhold, *elm_thumbscroll_friction;
 
 EAPI void
 elm_quicklaunch_init(int argc, char **argv)
@@ -121,6 +123,10 @@ elm_quicklaunch_init(int argc, char **argv)
    elm_font_cache = getenv("ELM_FONT_CACHE");
    elm_finger_size = getenv("ELM_FINGER_SIZE");
    elm_fps = getenv("ELM_FPS");
+   elm_thumbscroll_enabled = getenv("ELM_THUMBSCROLL_ENABLE");
+   elm_thumbscroll_threshhold = getenv("ELM_THUMBSCROLL_THRESHOLD");
+   elm_thumbscroll_momentum_threshhold = getenv("ELM_THUMBSCROLL_MOMENTUM_THRESHOLD");
+   elm_thumbscroll_friction = getenv("ELM_THUMBSCROLL_FRICTION");
    
    if (!_elm_data_dir)
      {
@@ -174,7 +180,9 @@ elm_quicklaunch_init(int argc, char **argv)
    _elm_config->thumbscroll_enable = 1;
    _elm_config->thumbscroll_threshhold = 24;
    _elm_config->thumbscroll_momentum_threshhold = 100.0;
-   _elm_config->thumbscroll_friction = 20.0;
+   _elm_config->thumbscroll_friction = 1.0;
+   _elm_config->thumbscroll_bounce_friction = 0.5;
+   _elm_config->thumbscroll_bounce_enable = 1;
    _elm_config->scale = 1.0;
    _elm_config->font_hinting = 2;
    _elm_config->font_dirs = NULL;
@@ -221,6 +229,16 @@ elm_quicklaunch_init(int argc, char **argv)
           _elm_config->engine = ELM_SOFTWARE_16_WINCE;
      }
    
+   if (elm_thumbscroll_enabled)
+     _elm_config->thumbscroll_enable = atoi(elm_thumbscroll_enabled);
+   if (elm_thumbscroll_threshhold)
+     _elm_config->thumbscroll_threshhold = atoi(elm_thumbscroll_threshhold);
+   // FIXME: floatformat locale issues here 1.0 vs 1,0 - should just be 1.0
+   if (elm_thumbscroll_momentum_threshhold)
+     _elm_config->thumbscroll_momentum_threshhold = atof(elm_thumbscroll_momentum_threshhold);
+   if (elm_thumbscroll_friction)
+     _elm_config->thumbscroll_friction = atof(elm_thumbscroll_friction);
+   
    if (elm_theme)
      _elm_theme_parse(elm_theme);
    else
@@ -349,7 +367,8 @@ elm_quicklaunch_sub_shutdown(void)
         ecore_event_handler_del(_elm_event_property_change);
         _elm_event_property_change = NULL;
         ecore_x_disconnect();
-#endif        
+#endif
+        evas_cserve_disconnect();
      }
 }
 
index b88d9a0..4776578 100644 (file)
@@ -41,6 +41,8 @@ struct _Elm_Config
    int thumbscroll_threshhold;
    double thumbscroll_momentum_threshhold;
    double thumbscroll_friction;
+   double thumbscroll_bounce_friction;
+   int thumbscroll_bounce_enable;
    double scale;
    int bgpixmap;
    int compositing;
index c26d609..2800f54 100644 (file)
@@ -137,6 +137,36 @@ _resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
    _sizing_eval(data);
 }
 
+static void
+_edge_left(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "edge_left", NULL);
+}
+
+static void
+_edge_right(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "edge_right", NULL);
+}
+
+static void
+_edge_top(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "edge_top", NULL);
+}
+
+static void
+_edge_bottom(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "edge_bottom", NULL);
+}
+
+static void
+_scroll(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "scroll", NULL);
+}
+
 EAPI Evas_Object *
 elm_scroller_add(Evas_Object *parent)
 {
@@ -167,6 +197,12 @@ elm_scroller_add(Evas_Object *parent)
    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
    
+   evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
+   evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
+   evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
+   evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
+   evas_object_smart_callback_add(wd->scr, "scroll", _scroll, obj);
+   
    _sizing_eval(obj);
    return obj;
 }
@@ -232,3 +268,19 @@ elm_scroller_region_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coo
    if ((x) && (y)) elm_smart_scroller_child_pos_get(wd->scr, x, y);
    if ((w) && (h)) elm_smart_scroller_child_viewport_size_get(wd->scr, w, h);
 }
+
+EAPI void
+elm_scroller_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_geometry_get(wd->content, NULL, NULL, w, h);
+}
+
+EAPI void
+elm_scroller_bounce_set(Evas_Object *obj, Evas_Bool h_bounce, Evas_Bool v_bounce)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
+}
index 87db110..ac4424b 100644 (file)
@@ -185,6 +185,7 @@ elm_toolbar_add(Evas_Object *parent)
    elm_widget_can_focus_set(obj, 0);
    
    wd->scr = elm_smart_scroller_add(e);
+   elm_scroller_bounce_set(wd->scr, 1, 0);
    elm_smart_scroller_theme_set(wd->scr, "toolbar", "base", "default");
    elm_widget_resize_object_set(obj, wd->scr);
    elm_smart_scroller_policy_set(wd->scr, 
index 2fa9d97..941cab3 100644 (file)
@@ -162,7 +162,12 @@ _els_smart_box_unpack(Evas_Object *obj)
    if (!sd) return;
    sd->items = eina_list_remove(sd->items, obj);
    _smart_disown(obj);
-   if (!sd->deleting) _smart_reconfigure(sd);
+   if (!sd->deleting)
+     {
+        if (!evas_object_clipees_get(sd->clip))
+          evas_object_hide(sd->clip);
+        _smart_reconfigure(sd);
+     }
 }
 
 /* local subsystem functions */
index 4e81078..78175a3 100644 (file)
@@ -356,6 +356,7 @@ _smart_add(Evas_Object *obj)
    sd = calloc(1, sizeof(Smart_Data));
    if (!sd) return;
    sd->obj = evas_object_image_add(evas_object_evas_get(obj));
+   evas_object_image_scale_hint_set(sd->obj, EVAS_IMAGE_SCALE_HINT_STATIC);
    sd->x = 0;
    sd->y = 0;
    sd->w = 0;
index b63420a..f032b5a 100644 (file)
@@ -87,10 +87,10 @@ void
 _elm_smart_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
 {
    API_ENTRY return;
-   if (x > (sd->child_w - sd->w)) x = sd->child_w - sd->w;
-   if (y > (sd->child_h - sd->h)) y = sd->child_h - sd->h;
-   if (x < 0) x = 0;
-   if (y < 0) y = 0;
+//   if (x > (sd->child_w - sd->w)) x = sd->child_w - sd->w;
+//   if (y > (sd->child_h - sd->h)) y = sd->child_h - sd->h;
+//   if (x < 0) x = 0;
+//   if (y < 0) y = 0;
    if ((x == sd->px) && (y == sd->py)) return;
    sd->px = x;
    sd->py = y;
index 8a00f9a..e1cdf3a 100644 (file)
@@ -22,22 +22,34 @@ struct _Smart_Data
       Evas_Coord x, y;
       Evas_Coord sx, sy;
       Evas_Coord dx, dy;
+      Evas_Coord bx, by;
+      Evas_Coord ax, ay;
+      Evas_Coord bx0, by0;
+      Evas_Coord b0x, b0y;
+      Evas_Coord b2x, b2y;
       struct {
         Evas_Coord    x, y;
         double        timestamp;
       } history[20];
       double anim_start;
+      double anim_start2;
+      double anim_start3;
       double onhold_vx, onhold_vy, onhold_tlast, onhold_vxe, onhold_vye;
       Evas_Coord hold_x, hold_y;
       Ecore_Animator *hold_animator;
-      Ecore_Animator *momentum_animator;
       Ecore_Animator *onhold_animator;
+      Ecore_Animator *momentum_animator;
+      Ecore_Animator *bounce_x_animator;
+      Ecore_Animator *bounce_y_animator;
       Evas_Coord locked_x, locked_y;
       unsigned char now : 1;
       unsigned char dragged : 1;
       unsigned char dir_x : 1;
       unsigned char dir_y : 1;
+      unsigned char dir_none : 1;
       unsigned char locked : 1;
+      unsigned char bounce_x_hold : 1;
+      unsigned char bounce_y_hold : 1;
    } down;
    
    struct {
@@ -61,6 +73,10 @@ struct _Smart_Data
    unsigned char one_dir_at_a_time : 1;
    unsigned char hold : 1;
    unsigned char freeze : 1;
+   unsigned char bouncemex : 1;
+   unsigned char bouncemey : 1;
+   unsigned char bounce_horiz : 1;
+   unsigned char bounce_vert : 1;
 }; 
 
 /* local subsystem functions */
@@ -215,6 +231,173 @@ elm_smart_scroller_custom_edje_file_set(Evas_Object *obj, char *file, char *grou
      edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,vbar", "elm");
 }
 
+static int
+_smart_bounce_x_animator(void *data)
+{
+   Smart_Data *sd;
+   Evas_Coord x, y, dx, dy/*, ox, oy*/;
+   double t, p, dt;
+   
+   sd = data;
+   t = ecore_loop_time_get();
+   dt = t - sd->down.anim_start2;
+   if (dt >= 0.0)
+     {
+       dt = dt / _elm_config->thumbscroll_bounce_friction;
+       if (dt > 1.0) dt = 1.0;
+       p = 1.0 - ((1.0 - dt) * (1.0 - dt) * (1.0 - dt));
+        elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+        dx = sd->down.b2x - sd->down.bx;
+       dx = (dx * p);
+       x = sd->down.bx + dx;
+        elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+        if (dt >= 1.0)
+          {
+             if (sd->down.momentum_animator)
+               sd->down.bounce_x_hold = 1;
+             sd->down.bounce_x_animator = NULL;
+             sd->bouncemex = 0;
+             return 0;
+          }
+     }
+   return 1;
+}
+
+static int
+_smart_bounce_y_animator(void *data)
+{
+   Smart_Data *sd;
+   Evas_Coord x, y, dx, dy;
+   double t, p, dt;
+   
+   sd = data;
+   t = ecore_loop_time_get();
+   dt = t - sd->down.anim_start3;
+   if (dt >= 0.0)
+     {
+       dt = dt / _elm_config->thumbscroll_bounce_friction;
+       if (dt > 1.0) dt = 1.0;
+       p = 1.0 - ((1.0 - dt) * (1.0 - dt) * (1.0 - dt));
+        elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+        dy = sd->down.b2y - sd->down.by;
+       dy = (dy * p);
+       y = sd->down.by + dy;
+        elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+        if (dt >= 1.0)
+          {
+             if (sd->down.momentum_animator)
+               sd->down.bounce_y_hold = 1;
+             sd->down.bounce_y_animator = NULL;
+             sd->bouncemey = 0;
+             return 0;
+          }
+     }
+   return 1;
+}
+
+static int
+_smart_momentum_animator(void *data)
+{
+   Smart_Data *sd;
+   double t, dt, p;
+   Evas_Coord x, y, dx, dy, px, py;
+   
+   sd = data;
+   t = ecore_loop_time_get();
+   dt = t - sd->down.anim_start;
+   if (dt >= 0.0)
+     {
+       dt = dt / _elm_config->thumbscroll_friction;
+       if (dt > 1.0) dt = 1.0;
+       p = 1.0 - ((1.0 - dt) * (1.0 - dt) * (1.0 - dt));
+       dx = (sd->down.dx * _elm_config->thumbscroll_friction * p);
+       dy = (sd->down.dy * _elm_config->thumbscroll_friction * p);
+        sd->down.ax = dx;
+        sd->down.ay = dy;
+       x = sd->down.sx - dx;
+       y = sd->down.sy - dy;
+        elm_smart_scroller_child_pos_get(sd->smart_obj, &px, &py);
+        if ((sd->down.bounce_x_animator) ||
+            (sd->down.bounce_x_hold))
+          {
+             sd->down.bx = sd->down.bx0 - dx + sd->down.b0x;
+             x = px;
+          }
+        if ((sd->down.bounce_y_animator) ||
+            (sd->down.bounce_y_hold))
+          {
+             sd->down.by = sd->down.by0 - dy + sd->down.b0y;
+             y = py;
+          }
+       elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+       if (dt >= 1.0)
+         {
+            sd->down.momentum_animator = NULL;
+             sd->down.bounce_x_hold = 0;
+             sd->down.bounce_y_hold = 0;
+             sd->down.ax = 0;
+             sd->down.ay = 0;
+            return 0;
+         }
+     }
+   return 1;
+}
+
+static void
+bounce_eval(Smart_Data *sd)
+{
+   Evas_Coord mx, my, px, py, bx, by, b2x, b2y;
+   
+   if ((!sd->bouncemex) && (!sd->bouncemey)) return;
+   if (sd->down.now) return; // down bounce while still held down
+   if (sd->down.onhold_animator)
+     {
+        ecore_animator_del(sd->down.onhold_animator);
+        sd->down.onhold_animator = NULL;
+     }
+   if (sd->down.hold_animator)
+     {
+        ecore_animator_del(sd->down.hold_animator);
+        sd->down.hold_animator = NULL;
+     }
+   sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+   bx = px;
+   by = py;
+   if (px < 0) px = 0;
+   if (px > mx) px = mx;
+   if (py < 0) py = 0;
+   if (py > my) py = my;
+   b2x = px;
+   b2y = py;
+   if (!sd->down.bounce_x_animator)
+     {
+        if (sd->bouncemex)
+          {
+             sd->down.bounce_x_animator = ecore_animator_add(_smart_bounce_x_animator, sd);
+             sd->down.anim_start2 = ecore_loop_time_get();
+             sd->down.bx = bx;
+             sd->down.bx0 = bx;
+             sd->down.b2x = b2x;
+             if (sd->down.momentum_animator) sd->down.b0x = sd->down.ax;
+             else sd->down.b0x = 0;
+          }
+     }
+   if (!sd->down.bounce_y_animator)
+     {
+        if (sd->bouncemey)
+          {
+             sd->down.bounce_y_animator = ecore_animator_add(_smart_bounce_y_animator, sd);
+             sd->down.anim_start3 = ecore_loop_time_get();
+             sd->down.by = by;
+             sd->down.by0 = by;
+             sd->down.b2y = b2y;
+             if (sd->down.momentum_animator) sd->down.b0y = sd->down.ay;
+             else sd->down.b0y = 0;
+          }
+     }
+}
+
 void
 elm_smart_scroller_child_pos_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
 {
@@ -235,9 +418,62 @@ elm_smart_scroller_child_pos_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
    edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, vy);
    edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", vx, 0.0);
    sd->pan_func.get(sd->pan_obj, &px, &py);
+   if (!_elm_config->thumbscroll_bounce_enable)
+     {
+        if (x < 0) x = 0;
+        if (x > mx) x = mx;
+        if (y < 0) y = 0;
+        if (y > my) y = my;
+     }
+
+   if (!sd->bounce_horiz)
+     {
+        if (x < 0) x = 0;
+        if (x > mx) x = mx;
+     }
+   if (!sd->bounce_vert)
+     {
+        if (y < 0) y = 0;
+        if (y > my) y = my;
+     }
+   
    sd->pan_func.set(sd->pan_obj, x, y);
    if ((px != x) || (py != y))
      edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
+   if (!sd->down.bounce_x_animator)
+     {
+        if ((x < 0) || (x > mx))
+          {
+             sd->bouncemex = 1;
+             bounce_eval(sd);
+          }
+     }
+   if (!sd->down.bounce_y_animator)
+     {
+        if ((y < 0) || (y > my))
+          {
+             sd->bouncemey = 1;
+             bounce_eval(sd);
+          }
+     }
+   if ((x != px) || (y != py))
+     {
+        evas_object_smart_callback_call(obj, "scroll", NULL);
+     }
+   if ((x != px)/* && (!sd->bouncemex)*/)
+     {
+        if (x == 0)
+          evas_object_smart_callback_call(obj, "edge,left", NULL);
+        if (x == mx)
+          evas_object_smart_callback_call(obj, "edge,right", NULL);
+     }
+   if ((y != py)/* && (!sd->bouncemey)*/)
+     {
+        if (y == 0)
+          evas_object_smart_callback_call(obj, "edge,top", NULL);
+        if (y == my)
+          evas_object_smart_callback_call(obj, "edge,bottom", NULL);
+     }
 }
 
 void
@@ -272,6 +508,18 @@ elm_smart_scroller_child_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord
        if (ny > y) ny = y;
      }
    if ((nx == px) && (ny == py)) return;
+   if (sd->down.bounce_x_animator)
+     {
+        ecore_animator_del(sd->down.bounce_x_animator);
+        sd->down.bounce_x_animator = NULL;
+        sd->bouncemex = 0;
+     }
+   if (sd->down.bounce_y_animator)
+     {
+        ecore_animator_del(sd->down.bounce_y_animator);
+        sd->down.bounce_y_animator = NULL;
+        sd->bouncemey = 0;
+     }
    elm_smart_scroller_child_pos_set(obj, nx, ny);
 }
 
@@ -404,6 +652,14 @@ elm_smart_scroller_freeze_set(Evas_Object *obj, Evas_Bool freeze)
      }
 }
 
+void
+elm_smart_scroller_bounce_allow_set(Evas_Object *obj, Evas_Bool horiz, Evas_Bool vert)
+{
+   API_ENTRY return;
+   sd->bounce_horiz = horiz;
+   sd->bounce_vert = vert;
+}
+
 /* local subsystem functions */
 static void
 _smart_edje_drag_v(void *data, Evas_Object *obj, const char *emission, const char *source)
@@ -437,10 +693,24 @@ _smart_child_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info)
 static void
 _smart_pan_changed_hook(void *data, Evas_Object *obj, void *event_info)
 {
+   Evas_Coord x, y;
    Evas_Coord w, h;
    Smart_Data *sd;
    
    sd = data;
+   if (sd->down.bounce_x_animator)
+     {
+        ecore_animator_del(sd->down.bounce_x_animator);
+        sd->down.bounce_x_animator = NULL;
+        sd->bouncemex = 0;
+     }
+   if (sd->down.bounce_y_animator)
+     {
+        ecore_animator_del(sd->down.bounce_y_animator);
+        sd->down.bounce_y_animator = NULL;
+        sd->bouncemey = 0;
+     }
+   sd->pan_func.get(sd->pan_obj, &x, &y);
    sd->pan_func.child_size_get(sd->pan_obj, &w, &h);
    if ((w != sd->child.w) || (h != sd->child.h))
      {
@@ -448,6 +718,7 @@ _smart_pan_changed_hook(void *data, Evas_Object *obj, void *event_info)
        sd->child.h = h;
        _smart_scrollbar_size_adjust(sd);
         evas_object_size_hint_min_set(sd->smart_obj, sd->child.w, sd->child.h);
+        elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
      }
 }
 
@@ -459,6 +730,18 @@ _smart_pan_pan_changed_hook(void *data, Evas_Object *obj, void *event_info)
    
    sd = data;
    sd->pan_func.get(sd->pan_obj, &x, &y);
+   if (sd->down.bounce_x_animator)
+     {
+        ecore_animator_del(sd->down.bounce_x_animator);
+        sd->down.bounce_x_animator = NULL;
+        sd->bouncemex = 0;
+     }
+   if (sd->down.bounce_y_animator)
+     {
+        ecore_animator_del(sd->down.bounce_y_animator);
+        sd->down.bounce_y_animator = NULL;
+        sd->bouncemey = 0;
+     }
    elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
 }
 
@@ -473,6 +756,12 @@ _smart_event_wheel(void *data, Evas *e, Evas_Object *obj, void *event_info)
    ev = event_info;
    elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
    y += ev->z * sd->step.y;
+   if (sd->down.bounce_y_animator)
+     {
+        ecore_animator_del(sd->down.bounce_y_animator);
+        sd->down.bounce_y_animator = NULL;
+        sd->bouncemey = 0;
+     }
    elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
 }
 
@@ -487,6 +776,18 @@ _smart_event_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
    ev = event_info;
    if (_elm_config->thumbscroll_enable)
      {
+        if (sd->down.bounce_x_animator)
+          {
+             ecore_animator_del(sd->down.bounce_x_animator);
+             sd->down.bounce_x_animator = NULL;
+             sd->bouncemex = 0;
+          }
+        if (sd->down.bounce_y_animator)
+          {
+             ecore_animator_del(sd->down.bounce_y_animator);
+             sd->down.bounce_y_animator = NULL;
+             sd->bouncemey = 0;
+          }
        if (sd->down.hold_animator)
          {
             ecore_animator_del(sd->down.hold_animator);
@@ -496,6 +797,10 @@ _smart_event_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
          {
             ecore_animator_del(sd->down.momentum_animator);
             sd->down.momentum_animator = NULL;
+             sd->down.bounce_x_hold = 0;
+             sd->down.bounce_y_hold = 0;
+             sd->down.ax = 0;
+             sd->down.ay = 0;
          }
        if (ev->button == 1)
          {
@@ -503,6 +808,7 @@ _smart_event_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
             sd->down.dragged = 0;
             sd->down.dir_x = 0;
             sd->down.dir_y = 0;
+            sd->down.dir_none = 0;
             sd->down.x = ev->canvas.x;
             sd->down.y = ev->canvas.y;
             elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
@@ -510,7 +816,7 @@ _smart_event_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
             sd->down.sy = y;
             sd->down.locked = 0;
             memset(&(sd->down.history[0]), 0, sizeof(sd->down.history[0]) * 20);
-            sd->down.history[0].timestamp = ecore_time_get();
+            sd->down.history[0].timestamp = ecore_loop_time_get();
             sd->down.history[0].x = ev->canvas.x;
             sd->down.history[0].y = ev->canvas.y;
          }
@@ -528,35 +834,6 @@ _smart_hold_animator(void *data)
    return 0;
 }
 
-static int
-_smart_momentum_animator(void *data)
-{
-   Smart_Data *sd;
-   double t, dt, p;
-   Evas_Coord x, y, dx, dy;
-   
-   sd = data;
-   t = ecore_time_get();
-   dt = t - sd->down.anim_start;
-   if (dt >= 0.0)
-     {
-       dt = dt / _elm_config->thumbscroll_friction;
-       if (dt > 1.0) dt = 1.0;
-       p = 1.0 - ((1.0 - dt) * (1.0 - dt) * (1.0 - dt));
-       dx = (sd->down.dx * _elm_config->thumbscroll_friction * p);
-       dy = (sd->down.dy * _elm_config->thumbscroll_friction * p);
-       x = sd->down.sx - dx;
-       y = sd->down.sy - dy;
-       elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
-       if (dt >= 1.0)
-         {
-            sd->down.momentum_animator = NULL;
-            return 0;
-         }
-     }
-   return 1;
-}
-
 static void
 _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
 {
@@ -586,7 +863,7 @@ _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
                        int i;
                        Evas_Coord ax, ay, dx, dy, vel;
                        
-                       t = ecore_time_get();
+                       t = ecore_loop_time_get();
                        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
                        ax = ev->canvas.x;
                        ay = ev->canvas.y;
@@ -624,6 +901,8 @@ _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
                                  elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
                                  sd->down.sx = x;
                                  sd->down.sy = y;
+                                 sd->down.b0x = 0;
+                                 sd->down.b0y = 0;
                               }
                          }
                     }
@@ -631,6 +910,9 @@ _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
               }
             sd->down.dragged = 0;
             sd->down.now = 0;
+             elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+             elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+             bounce_eval(sd);
          }
      }
 }
@@ -677,9 +959,11 @@ _smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info)
      {
        if (sd->down.now)
          {
+             int faildir = 0;
+             
             memmove(&(sd->down.history[1]), &(sd->down.history[0]),
                     sizeof(sd->down.history[0]) * 19);
-            sd->down.history[0].timestamp = ecore_time_get();
+            sd->down.history[0].timestamp = ecore_loop_time_get();
             sd->down.history[0].x = ev->cur.canvas.x;
             sd->down.history[0].y = ev->cur.canvas.y;
             
@@ -688,24 +972,27 @@ _smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info)
             y = ev->cur.canvas.y - sd->down.y;
             if (y < 0) y = -y;
             if ((sd->one_dir_at_a_time) && 
-                (!sd->down.dir_x) && (!sd->down.dir_y))
+                (!sd->down.dir_x) && (!sd->down.dir_y) && (!sd->down.dir_none))
               {
-                 if (x > y)
-                   {
-                      if (x > _elm_config->thumbscroll_threshhold)
-                        {
+                  if (x > _elm_config->thumbscroll_threshhold)
+                    {
+                       if (x > (y * 2))
+                         {
                            sd->down.dir_x = 1;
                            sd->down.dir_y = 0;
                         }
+                       else faildir++;
                    }
-                 else
+                  if (y > _elm_config->thumbscroll_threshhold)
                    {
-                      if (y > _elm_config->thumbscroll_threshhold)
+                       if (y > (x * 2))
                         {
                            sd->down.dir_x = 0;
                            sd->down.dir_y = 1;
-                        }
+                         }
+                       else faildir++;
                    }
+                  if (faildir) sd->down.dir_none = 1;
               }
              if (!sd->hold)
                {
@@ -809,6 +1096,7 @@ _smart_event_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
    Evas_Event_Key_Down *ev;
    Smart_Data *sd;
    Evas_Coord x = 0, y = 0, vw = 0, vh = 0, mx = 0, my = 0;
+   int xch = 0, ych = 0;
    
    sd = data;
    ev = event_info;
@@ -817,23 +1105,42 @@ _smart_event_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
    sd->pan_func.max_get(sd->pan_obj, &mx, &my);
    evas_object_geometry_get(sd->pan_obj, NULL, NULL, &vw, &vh);
    if (!strcmp(ev->keyname, "Left"))
-     x -= sd->step.x;
+     {
+        x -= sd->step.x;
+        xch = 1;
+     }
    else if (!strcmp(ev->keyname, "Right"))
-     x += sd->step.x;
+     {
+        x += sd->step.x;
+        xch = 1;
+     }
    else if (!strcmp(ev->keyname, "Up"))
-     y -= sd->step.y;
+     {
+        y -= sd->step.y;
+        ych = 1;
+     }
    else if (!strcmp(ev->keyname, "Home"))
-     y = 0;
+     {
+        y = 0;
+        ych = 1;
+     }
    else if (!strcmp(ev->keyname, "End"))
-     y = my;
+     {
+        y = my;
+        ych = 1;
+     }
    else if (!strcmp(ev->keyname, "Down"))
-     y += sd->step.y;
+     {
+        y += sd->step.y;
+        ych = 1;
+     }
    else if (!strcmp(ev->keyname, "Prior"))
      {
        if (sd->page.y < 0)
          y -= -(sd->page.y * vh) / 100;
        else
          y -= sd->page.y;
+        ych = 1;
      }
    else if (!strcmp(ev->keyname, "Next"))
      {
@@ -841,7 +1148,27 @@ _smart_event_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
          y += -(sd->page.y * vh) / 100;
        else
          y += sd->page.y;
+        ych = 1;
+     }
+   if (xch)
+     {
+        if (sd->down.bounce_x_animator)
+          {
+             ecore_animator_del(sd->down.bounce_x_animator);
+             sd->down.bounce_x_animator = NULL;
+             sd->bouncemex = 0;
+          }
+     }
+   if (ych)
+     {
+        if (sd->down.bounce_y_animator)
+          {
+             ecore_animator_del(sd->down.bounce_y_animator);
+             sd->down.bounce_y_animator = NULL;
+             sd->bouncemey = 0;
+          }
      }
+
    elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
 }
 
@@ -1135,6 +1462,11 @@ _smart_add(Evas_Object *obj)
    sd->hbar_visible = 1;
    sd->vbar_visible = 1;
    
+   sd->bounce_horiz = 1;
+   sd->bounce_vert = 1;
+   
+   sd->one_dir_at_a_time = 1;
+   
    evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN, _smart_event_key_down, sd);
    evas_object_propagate_events_set(obj, 0);
    
@@ -1180,7 +1512,10 @@ _smart_del(Evas_Object *obj)
    evas_object_del(sd->edje_obj);
    evas_object_del(sd->event_obj);
    if (sd->down.hold_animator) ecore_animator_del(sd->down.hold_animator);
+   if (sd->down.onhold_animator) ecore_animator_del(sd->down.onhold_animator);
    if (sd->down.momentum_animator) ecore_animator_del(sd->down.momentum_animator);
+   if (sd->down.bounce_x_animator) ecore_animator_del(sd->down.bounce_x_animator);
+   if (sd->down.bounce_y_animator) ecore_animator_del(sd->down.bounce_y_animator);
    free(sd);
    evas_object_smart_data_set(obj, NULL);
 }
index 0d9c936..0076148 100644 (file)
@@ -26,3 +26,4 @@ Evas_Bool elm_smart_scroller_single_dir_get     (Evas_Object *obj);
 void elm_smart_scroller_theme_set               (Evas_Object *obj, const char *clas, const char *group, const char *style);
 void elm_smart_scroller_hold_set                (Evas_Object *obj, Evas_Bool hold);
 void elm_smart_scroller_freeze_set              (Evas_Object *obj, Evas_Bool freeze);
+void elm_smart_scroller_bounce_allow_set        (Evas_Object *obj, Evas_Bool horiz, Evas_Bool vert);