1. brian wang's patch for setting item count in a block, and homogenous
authorCarsten Haitzler <raster@rasterman.com>
Sat, 23 Jan 2010 09:07:20 +0000 (09:07 +0000)
committerCarsten Haitzler <raster@rasterman.com>
Sat, 23 Jan 2010 09:07:20 +0000 (09:07 +0000)
genlist mode, button repeat stuff. thanks very muchly

also - i added calc idler self-timer check. if it spends more than 1
frametime (time between frames - this is what it deems as "too much") on
calculation, then it breaks the idle and goes back to mainloop. could make it
half a frametime - but this will do for now.

SVN revision: 45479

AUTHORS
src/lib/Elementary.h.in
src/lib/elm_genlist.c

diff --git a/AUTHORS b/AUTHORS
index 7c06ab839bffc0e0ea29dec51609d2af63d82742..cee771bb2f5ed5af3c8c5748190d1d4d9c21510a 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -9,3 +9,5 @@ Christopher Michael <devilhorns@devilhorns.us>
 Marco Trevisan (TreviƱo) <mail@3v1n0.net>
 Michael Bouchaud <michael.bouchaud@gmail.com>
 Jonathan Atton (Watchwolf) <jonathan.atton@gmail.com>
+Brian Wang <brian.wang.0721@gmail.com>
+
index 3a37f436a57597a718029db030a2bad9508d2d8d..0ad862731f98855a0a3996fe423d6e0405b2f1e4 100644 (file)
@@ -374,6 +374,9 @@ extern "C" {
    EAPI const char  *elm_button_label_get(Evas_Object *obj);
    EAPI void         elm_button_icon_set(Evas_Object *obj, Evas_Object *icon);
    EAPI Evas_Object *elm_button_icon_get(Evas_Object *obj);
+   EAPI void         elm_button_autorepeat_set(Evas_Object *obj, Eina_Bool on);
+   EAPI void         elm_button_autorepeat_initital_timeout_set(Evas_Object *obj, double t);
+   EAPI void         elm_button_autorepeat_gap_timeout_set(Evas_Object *obj, double t);
    EINA_DEPRECATED EAPI void elm_button_style_set(Evas_Object *obj, const char *style);
    /* available styles:
     * default
@@ -383,6 +386,7 @@ extern "C" {
     */
    /* smart callbacks called:
     * "clicked" - the user clicked the button
+    * "repeated" - the user pressed the button without releasing it
     */
 
    typedef enum _Elm_Scroller_Policy
@@ -882,6 +886,8 @@ extern "C" {
    EAPI void              elm_genlist_no_select_mode_set(Evas_Object *obj, Eina_Bool no_select);
    EAPI void              elm_genlist_compress_mode_set(Evas_Object *obj, Eina_Bool compress);
    EAPI void              elm_genlist_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce);
+   EAPI void              elm_genlist_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous);
+   EAPI void              elm_genlist_block_count_set(Evas_Object *obj, int n);
    /* available item styles:
     * default
     * default_style - The text part is a textblock
index 7c005cfe5ed7a180fc44888458b1ddad700c80ad..d379f0403b95c329a3e586535e06875d36589d04 100644 (file)
@@ -1,3 +1,7 @@
+/*
+ *
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
 #include <Elementary.h>
 #include "elm_priv.h"
 
  * have a specific style that overrides any theme the user or system sets up
  * you can use elm_theme_overlay_add() to add such a file.
  */
+
 typedef struct _Widget_Data Widget_Data;
 typedef struct _Item_Block Item_Block;
 typedef struct _Pan Pan;
@@ -260,18 +265,24 @@ struct _Widget_Data
    Eina_Bool no_select : 1;
    Eina_Bool bring_in : 1;
    Eina_Bool compress : 1;
+   Eina_Bool homogeneous : 1;
+   int item_width;
+   int item_height;
+   int max_items_per_block;
 };
 
 struct _Item_Block
 {
    EINA_INLIST;
    int count;
+   int num;
    Widget_Data *wd;
    Eina_List *items;
    Evas_Coord x, y, w, h, minw, minh;
    Eina_Bool realized : 1;
    Eina_Bool changed : 1;
    Eina_Bool updateme : 1;
+   Eina_Bool showme : 1;
 };
 
 struct _Elm_Genlist_Item
@@ -691,12 +702,12 @@ _item_realize(Elm_Genlist_Item *it, int in, int calc)
    elm_widget_sub_object_add(it->wd->obj, it->base);
 
    if (it->flags & ELM_GENLIST_ITEM_SUBITEMS) strncpy(buf, "tree", sizeof(buf));
-   else strncpy(buf, "item", sizeof(buf)); 
-   if (it->wd->compress) strncat(buf, "_compress", sizeof(buf));
+   else strncpy(buf, "item", sizeof(buf));
+   if (it->wd->compress) strncat(buf, "_compress", sizeof(buf) - strlen(buf));
 
-   if (in & 0x1) strncat(buf, "_odd", sizeof(buf));
-   strncat(buf, "/", sizeof(buf));
-   strncat(buf, it->itc->item_style, sizeof(buf));
+   if (in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
+   strncat(buf, "/", sizeof(buf) - strlen(buf));
+   strncat(buf, it->itc->item_style, sizeof(buf) - strlen(buf));
    
    _elm_theme_set(it->base, "genlist", buf, elm_widget_style_get(it->wd->obj));
    it->spacer = evas_object_rectangle_add(evas_object_evas_get(it->wd->obj));
@@ -736,71 +747,90 @@ _item_realize(Elm_Genlist_Item *it, int in, int calc)
          edje_object_signal_emit(it->base, "elm,state,expanded", "elm");
      }
 
-   if (it->itc->func.label_get)
+   if (calc && it->wd->homogeneous && it->wd->item_width)
      {
-       const Eina_List *l;
-       const char *key;
-
-       it->labels = _stringlist_get(edje_object_data_get(it->base, "labels"));
-       EINA_LIST_FOREACH(it->labels, l, key)
+       /* homogenous genlist shortcut */
+       if (!it->mincalcd)
          {
-            char *s = it->itc->func.label_get(it->data, it->wd->obj, l->data);
-
-            if (s)
-              {
-                 edje_object_part_text_set(it->base, l->data, s);
-                 free(s);
-              }
+            it->w = it->minw = it->wd->item_width;
+            it->h = it->minh = it->wd->item_height;
+            it->mincalcd = EINA_TRUE;
          }
      }
-   if (it->itc->func.icon_get)
+   else
      {
-       const Eina_List *l;
-       const char *key;
-
-       it->icons = _stringlist_get(edje_object_data_get(it->base, "icons"));
-       EINA_LIST_FOREACH(it->icons, l, key)
+       if (it->itc->func.label_get)
          {
-            Evas_Object *ic = it->itc->func.icon_get(it->data, it->wd->obj, l->data);
+            const Eina_List *l;
+            const char *key;
 
-            if (ic)
+            it->labels = _stringlist_get(edje_object_data_get(it->base, "labels"));
+            EINA_LIST_FOREACH(it->labels, l, key)
               {
-                 it->icon_objs = eina_list_append(it->icon_objs, ic);
-                 edje_object_part_swallow(it->base, key, ic);
-                 evas_object_show(ic);
-                 elm_widget_sub_object_add(it->wd->obj, ic);
+                 char *s = it->itc->func.label_get(it->data, it->wd->obj, l->data);
+
+                 if (s)
+                   {
+                      edje_object_part_text_set(it->base, l->data, s);
+                      free(s);
+                   }
               }
          }
-     }
-   if (it->itc->func.state_get)
-     {
-       const Eina_List *l;
-       const char *key;
+       if (it->itc->func.icon_get)
+         {
+            const Eina_List *l;
+            const char *key;
+
+            it->icons = _stringlist_get(edje_object_data_get(it->base, "icons"));
+            EINA_LIST_FOREACH(it->icons, l, key)
+              {
+                 Evas_Object *ic = it->itc->func.icon_get(it->data, it->wd->obj, l->data);
 
-       it->states = _stringlist_get(edje_object_data_get(it->base, "states"));
-       EINA_LIST_FOREACH(it->states, l, key)
+                 if (ic)
+                   {
+                      it->icon_objs = eina_list_append(it->icon_objs, ic);
+                      edje_object_part_swallow(it->base, key, ic);
+                      evas_object_show(ic);
+                      elm_widget_sub_object_add(it->wd->obj, ic);
+                   }
+              }
+         }
+       if (it->itc->func.state_get)
          {
-            Eina_Bool on = it->itc->func.state_get(it->data, it->wd->obj, l->data);
+            const Eina_List *l;
+            const char *key;
 
-            if (on)
+            it->states = _stringlist_get(edje_object_data_get(it->base, "states"));
+            EINA_LIST_FOREACH(it->states, l, key)
               {
-                 snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
-                 edje_object_signal_emit(it->base, buf, "elm");
+                 Eina_Bool on = it->itc->func.state_get(it->data, it->wd->obj, l->data);
+
+                 if (on)
+                   {
+                      snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
+                      edje_object_signal_emit(it->base, buf, "elm");
+                   }
               }
          }
-     }
-   if (!it->mincalcd)
-     {
-       Evas_Coord mw = -1, mh = -1;
+       if (!it->mincalcd)
+         {
+            Evas_Coord mw = -1, mh = -1;
 
-       elm_coords_finger_size_adjust(1, &mw, 1, &mh);
-       edje_object_size_min_restricted_calc(it->base, &mw, &mh, mw, mh);
-       elm_coords_finger_size_adjust(1, &mw, 1, &mh);
-       it->w = it->minw = mw;
-       it->h = it->minh = mh;
-       it->mincalcd = EINA_TRUE;
+            elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+            edje_object_size_min_restricted_calc(it->base, &mw, &mh, mw, mh);
+            elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+            it->w = it->minw = mw;
+            it->h = it->minh = mh;
+            it->mincalcd = EINA_TRUE;
+
+            if (in == 0 && it->wd->homogeneous)
+              {
+                 it->wd->item_width = mw;
+                 it->wd->item_height = mh;
+              }
+         }
+       if (!calc) evas_object_show(it->base);
      }
-   if (!calc) evas_object_show(it->base);
    it->realized = EINA_TRUE;
 }
 
@@ -829,22 +859,35 @@ _item_unrealize(Elm_Genlist_Item *it)
 }
 
 static int
-_item_block_recalc(Item_Block *itb, int in)
+_item_block_recalc(Item_Block *itb, int in, int qadd)
 {
    const Eina_List *l;
    Elm_Genlist_Item *it;
    Evas_Coord minw = 0, minh = 0;
-   int showme = 0;
+   int showme = 0, changed = 0;
    Evas_Coord y = 0;
 
+   itb->num = in;
    EINA_LIST_FOREACH(itb->items, l, it)
      {
        if (it->delete_me) continue;
        showme |= it->showme;
        if (!itb->realized)
          {
-            _item_realize(it, in, 1);
-            _item_unrealize(it);
+             if (qadd)
+               {
+                  if (!it->mincalcd) changed = 1;
+                  if (changed)
+                    {
+                       _item_realize(it, in, 1);
+                       _item_unrealize(it);
+                    }
+               }
+             else
+               {
+                  _item_realize(it, in, 1);
+                  _item_unrealize(it);
+               }
          }
        else
           {
@@ -975,14 +1018,13 @@ _calc_job(void *data)
    Item_Block *chb = NULL;
    int in = 0, minw_change = 0;
 
-   double t, t_start;
-   
-   t_start = ecore_time_get();
-   
    EINA_INLIST_FOREACH(wd->blocks, itb)
      {
        int showme = 0;
 
+        itb->num = in;
+        showme = itb->showme;
+        itb->showme = 0;
        if (chb)
          {
             if (itb->realized) _item_block_unrealize(itb);
@@ -990,7 +1032,7 @@ _calc_job(void *data)
        if (itb->changed)
          {
             if (itb->realized) _item_block_unrealize(itb);
-            showme = _item_block_recalc(itb, in);
+            showme = _item_block_recalc(itb, in, 0);
             chb = itb;
          }
        itb->y = y;
@@ -1049,11 +1091,6 @@ _calc_job(void *data)
      }
    wd->calc_job = NULL;
    evas_object_smart_changed(wd->pan_smart);
-   
-   t = ecore_time_get();
-#if 0
-   printf("calc job %1.5f\n", t - t_start);
-#endif
 }
 
 static void
@@ -1111,7 +1148,7 @@ _update_job(void *data)
           {
              position = 1;
              itb->changed = EINA_TRUE;
-             _item_block_recalc(itb, num0);
+             _item_block_recalc(itb, num0, 0);
              _item_block_position(itb, num0);
           }
      }
@@ -1311,6 +1348,7 @@ elm_genlist_add(Evas_Object *parent)
 
    wd->obj = obj;
    wd->mode = ELM_LIST_SCROLL;
+   wd->max_items_per_block = 32;
 
    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
@@ -1502,7 +1540,7 @@ _item_block_add(Widget_Data *wd, Elm_Genlist_Item *it)
                  if (wd->blocks)
                    {
                       itb = (Item_Block *)(wd->blocks);
-                      if (itb->count >= 32)
+                      if (itb->count >= wd->max_items_per_block)
                         {
                            itb = calloc(1, sizeof(Item_Block));
                            if (!itb) return;
@@ -1527,7 +1565,7 @@ _item_block_add(Widget_Data *wd, Elm_Genlist_Item *it)
                  if (wd->blocks)
                    {
                       itb = (Item_Block *)(wd->blocks->last);
-                      if (itb->count >= 32)
+                      if (itb->count >= wd->max_items_per_block)
                         {
                            itb = calloc(1, sizeof(Item_Block));
                            if (!itb) return;
@@ -1570,7 +1608,7 @@ _item_block_add(Widget_Data *wd, Elm_Genlist_Item *it)
          _item_del(it->rel);
        it->rel = NULL;
      }
-   if (itb->count > 32)
+   if (itb->count > itb->wd->max_items_per_block)
      {
         int newc;
         Item_Block *itb2;
@@ -1604,11 +1642,11 @@ static int
 _item_idler(void *data)
 {
    Widget_Data *wd = data;
-   int n;
-   double t_start, t;
+   int n, showme = 0;
+   double t0, t;
 
-   t_start = ecore_time_get();
-   for (n = 0; (wd->queue) && (n < 4); n++)
+   t0 = ecore_time_get();
+   for (n = 0; (wd->queue) && (n < 128); n++)
      {
        Elm_Genlist_Item *it;
 
@@ -1617,14 +1655,14 @@ _item_idler(void *data)
        it->queued = EINA_FALSE;
        _item_block_add(wd, it);
         t = ecore_time_get();
-        // FIXME: call calc job now
-//        if ((t - t_start) > ecore_animator_frametime_get())
-//          {
-//             printf("abort idler\n");
-//             break;
-//          }
-     }
-//   printf("%1.5f\n", t - t_start);
+        if (it->block->changed)
+          {
+             showme = _item_block_recalc(it->block, it->block->num, 1);
+             it->block->changed = 0;
+          }
+        if (showme) it->block->showme = 1;
+        if ((t - t0) > (ecore_animator_frametime_get())) break;
+     }
    if (n > 0)
      {
        if (wd->calc_job) ecore_job_del(wd->calc_job);
@@ -2729,3 +2767,43 @@ elm_genlist_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
    Widget_Data *wd = elm_widget_data_get(obj);
    elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
 }
+
+/**
+ * Set homogenous mode
+ *
+ * This will enable the homogeneous mode where items are of the same height and width
+ * so that genlist may do the lazy-loading at its maximum.  This implies 'compressed' mode
+ *
+ * @param obj The genlist object
+ * @param homogeneous Assume the items within the genlist are of the same height and width
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (homogeneous)
+      elm_genlist_compress_mode_set(obj, 1);
+   wd->homogeneous = homogeneous;
+}
+
+/**
+ * Set the maximum number of items within an item block
+ *
+ * This will configure the block count to tune to the target with particular performance matrix.
+ *
+ * @param obj The genlist object
+ * @param n   Maximum number of items within an item block
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_block_count_set(Evas_Object *obj, int n)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   wd->max_items_per_block = n;
+}
+
+