gengrid: support for non homogenous items
authorSangHyeon Lee <sh10233.lee@samsung.com>
Tue, 25 Oct 2016 05:06:31 +0000 (14:06 +0900)
committerTaehyub Kim <taehyub.kim@samsung.com>
Tue, 29 Nov 2016 12:32:35 +0000 (21:32 +0900)
This patch is forked by upstream commit
73095ad7ad7cf67c2c9a66787da6395bfbdd3e4a

Change-Id: I6743c39b95c2d9addde4303ce295e3985e539f27
Signed-off-by: SangHyeon Lee <sh10233.lee@samsung.com>
src/bin/test.c
src/bin/test_gengrid.c
src/lib/elm_gengrid.c
src/lib/elm_gengrid_item.eo
src/lib/elm_widget_gengrid.h

index 62fe4dabb7482a1728de7252fcf160a970929aac..d9b4dfc4964b970d2d0c90dd567061acf27e41c7 100644 (file)
@@ -148,6 +148,7 @@ void test_gengrid_speed(void *data, Evas_Object *obj, void *event_info);
 void test_gengrid_focus(void *data, Evas_Object *obj, void *event_info);
 void test_gengrid_update(void *data, Evas_Object *obj, void *event_info);
 void test_gengrid_disabled_item_focus(void *data, Evas_Object *obj, void *event_info);
+void test_gengrid_item_custom_size(void *data, Evas_Object *obj, void *event_info);
 void test_win_state(void *data, Evas_Object *obj, void *event_info);
 void test_win_state2(void *data, Evas_Object *obj, void *event_info);
 void test_progressbar(void *data, Evas_Object *obj, void *event_info);
@@ -716,6 +717,7 @@ add_tests:
    ADD_TEST(NULL, "Lists - Gengrid", "Gengrid Update Speed", test_gengrid_speed);
    ADD_TEST(NULL, "Lists - Gengrid", "GenGrid Focus", test_gengrid_focus);
    ADD_TEST(NULL, "Lists - Gengrid", "GenGrid Update", test_gengrid_update);
+   ADD_TEST(NULL, "Lists - Gengrid", "GenGrid Item Custom Size", test_gengrid_item_custom_size);
 
    //------------------------------//
    ADD_TEST(NULL, "General", "Scaling", test_scaling);
index 8f67c9b03759a62328f6c4c6f9fab119039a85d0..dfb2ac7e440cd10485f76e34ad768732e4528078 100644 (file)
@@ -5,6 +5,8 @@
 #endif
 #include <Elementary.h>
 
+#define ITEMS_MAX 50
+
 Evas_Object * _focus_autoscroll_mode_frame_create(Evas_Object *parent);
 
 static Elm_Gengrid_Item_Class *gic, *ggic;
@@ -2321,3 +2323,207 @@ test_gengrid_disabled_item_focus(void *data EINA_UNUSED,
    evas_object_resize(win, 600, 600);
    evas_object_show(win);
 }
+
+static void
+_enable_bringin(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+   if (elm_check_state_get(obj))
+     elm_config_focus_autoscroll_mode_set(ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN);
+   else
+     elm_config_focus_autoscroll_mode_set(ELM_FOCUS_AUTOSCROLL_MODE_SHOW);
+}
+
+typedef struct _item_resize_data{
+   Evas_Object *wentry, *hentry, *grid;
+}Item_Resize_Data;
+
+static void
+_custom_item_size(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Evas_Coord w = 0, h = 0;
+   Elm_Object_Item *it;
+   const char *pstr;
+   Item_Resize_Data *pdata;
+   if (!data) return;
+
+   pdata = data;
+   pstr = elm_object_text_get(pdata->wentry);
+   if (pstr) w = atoi(pstr);
+   pstr = elm_object_text_get(pdata->hentry);
+   if (pstr) h = atoi(pstr);
+   it = elm_gengrid_selected_item_get(pdata->grid);
+   if (it) elm_gengrid_item_custom_size_set(it, w, h);
+}
+
+static void
+_item_selected(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Evas_Coord w, h;
+   Item_Resize_Data *pdata;
+   char buf[8];
+   if (!data) return;
+
+   pdata = data;
+   elm_gengrid_item_custom_size_get(event_info, &w, &h);
+   if (snprintf(buf, 8, "%d", (int)w) > 7) buf[7] = 0;
+   elm_object_part_text_set(pdata->wentry, NULL, buf);
+   if (snprintf(buf, 8, "%d", (int)h) > 7) buf[7] = 0;
+   elm_object_part_text_set(pdata->hentry, NULL, buf);
+}
+
+void
+test_gengrid_item_custom_size(void *data EINA_UNUSED,
+                   Evas_Object *obj EINA_UNUSED,
+                   void *event_info EINA_UNUSED)
+{
+   Evas_Object *win, *hbox, *vbox, *ck, *grid, *en, *btn, *ebox, *lb;
+   Elm_Gengrid_Item_Class *ic;
+   Item_Data *id;
+   Item_Resize_Data *pdata;
+   char buf[PATH_MAX];
+   int i, n;
+
+   pdata = calloc(1, sizeof(Item_Resize_Data));
+
+   win = elm_win_util_standard_add("item custom size", "Item Custom Size");
+   elm_win_focus_highlight_enabled_set(win, EINA_TRUE);
+   evas_object_event_callback_add(win, EVAS_CALLBACK_FREE, _cleanup_cb, pdata);
+   elm_win_autodel_set(win, EINA_TRUE);
+   evas_object_show(win);
+
+   hbox = elm_box_add(win);
+   elm_box_horizontal_set(hbox, EINA_TRUE);
+   evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_win_resize_object_add(win, hbox);
+   evas_object_show(hbox);
+
+   /* box for gengrid */
+   vbox = elm_box_add(hbox);
+   evas_object_size_hint_weight_set(vbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(vbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(hbox, vbox);
+   evas_object_show(vbox);
+
+   grid = elm_gengrid_add(vbox);
+   /* Set default size of items even if elm_gengrid_item_custom_size_set()
+    * will be used to set custom size for individual item. */
+   elm_gengrid_item_size_set(grid, ELM_SCALE_SIZE(100), ELM_SCALE_SIZE(100));
+   elm_gengrid_horizontal_set(grid, EINA_TRUE);
+   evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(vbox, grid);
+   evas_object_show(grid);
+
+   pdata->grid = grid;
+
+   evas_object_smart_callback_add(grid, "item,focused", _gengrid_focus_item_cb, "item,focused");
+   evas_object_smart_callback_add(grid, "item,unfocused", _gengrid_focus_item_cb, "item,unfocused");
+   evas_object_smart_callback_add(grid, "selected", _gengrid_focus_item_cb, "selected");
+   evas_object_smart_callback_add(grid, "unselected", _gengrid_focus_item_cb, "unselected");
+   evas_object_smart_callback_add(grid, "activated", _gengrid_focus_item_cb, "activated");
+   evas_object_smart_callback_add(grid, "highlighted", _gengrid_focus_item_cb, "highlighted");
+   evas_object_smart_callback_add(grid, "unhighlighted", _gengrid_focus_item_cb, "unhighlighted");
+
+   /* box for options */
+   vbox = elm_box_add(hbox);
+   elm_box_padding_set(vbox, 0, 20);
+   evas_object_size_hint_weight_set(vbox, 0.0, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(vbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(hbox, vbox);
+   evas_object_show(vbox);
+
+   ebox = elm_box_add(vbox);
+   elm_box_padding_set(ebox, 0, 5);
+   evas_object_size_hint_weight_set(ebox, 0.0, 0.0);
+   evas_object_size_hint_align_set(ebox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(vbox, ebox);
+   evas_object_show(ebox);
+
+   lb = elm_label_add(ebox);
+   elm_object_text_set(lb, "Select an item...");
+   evas_object_size_hint_weight_set(lb, 0.0, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(lb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(ebox, lb);
+   evas_object_show(lb);
+
+   en = elm_entry_add(ebox);
+   elm_entry_single_line_set(en, EINA_TRUE);
+   elm_entry_scrollable_set(en, EINA_TRUE);
+   elm_object_part_text_set(en, "guide", "Width");
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(ebox, en);
+   evas_object_show(en);
+
+   pdata->wentry = en;
+
+   en = elm_entry_add(ebox);
+   elm_entry_single_line_set(en, EINA_TRUE);
+   elm_entry_scrollable_set(en, EINA_TRUE);
+   elm_object_part_text_set(en, "guide", "Height");
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(ebox, en);
+   evas_object_show(en);
+
+   pdata->hentry = en;
+
+   btn = elm_button_add(ebox);
+   elm_object_text_set(btn, "Resize Item");
+   evas_object_smart_callback_add(btn, "clicked", _custom_item_size, (void *)pdata);
+   elm_box_pack_end(ebox, btn);
+   evas_object_show(btn);
+
+   ebox = elm_box_add(vbox);
+   evas_object_size_hint_weight_set(ebox, 0.0, 0.0);
+   evas_object_size_hint_align_set(ebox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(vbox, ebox);
+   evas_object_show(ebox);
+
+   ck = elm_check_add(ebox);
+   elm_object_text_set(ck, "Horizontal Mode");
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, 0.0);
+   evas_object_smart_callback_add(ck, "changed", _horizontal_grid, grid);
+   elm_check_state_set(ck, EINA_TRUE);
+   elm_box_pack_end(ebox, ck);
+   evas_object_show(ck);
+
+   ck = elm_check_add(ebox);
+   elm_object_text_set(ck, "Bring-in");
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, 0.0);
+   evas_object_smart_callback_add(ck, "changed", _enable_bringin, grid);
+   elm_box_pack_end(ebox, ck);
+   evas_object_show(ck);
+
+   ck = elm_check_add(ebox);
+   elm_object_text_set(ck, "Item Loop");
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, 0.0);
+   evas_object_smart_callback_add(ck, "changed",_item_loop_enable_changed_cb, grid);
+   elm_box_pack_end(ebox, ck);
+   evas_object_show(ck);
+
+   ic = elm_gengrid_item_class_new();
+   ic->item_style = "default";
+   ic->func.text_get = grid_text_get;
+   ic->func.content_get = grid_content_get;
+   ic->func.state_get = NULL;
+   ic->func.del = grid_del;
+
+   n = 0;
+   for (i = 0; i < ITEMS_MAX; i++)
+     {
+        id = calloc(1, sizeof(Item_Data));
+        snprintf(buf, sizeof(buf), "%s/images/%s", elm_app_data_dir_get(), img[n]);
+        n = (n + 1) % 9;
+        id->mode = i;
+        id->path = eina_stringshare_add(buf);
+        id->item = elm_gengrid_item_append(grid, ic, id, _item_selected, pdata);
+        if (!(i % 2))
+          elm_gengrid_item_custom_size_set(id->item, ELM_SCALE_SIZE(40 + (2 * i)),
+                                           ELM_SCALE_SIZE(40 + (2 * i)));
+     }
+   elm_gengrid_item_class_free(ic);
+
+   evas_object_resize(win, 800, 600);
+}
index afcaf8d0d36cc357f5eefccb32858fdf5549c985..7ee1c5c063b647140abad749feb5c9d86083a60e 100644 (file)
@@ -273,6 +273,66 @@ _item_cache_find(Elm_Gen_Item *it)
    return EINA_FALSE;
 }
 
+//Calculate sum of widths or heights of all items in a row or column
+static int
+_get_item_span(Elm_Gengrid_Data *sd, int idx)
+{
+   Elm_Gen_Item *it;
+   int sum = 0;
+   idx++;
+
+   EINA_INLIST_FOREACH(sd->items, it)
+     {
+        if (it->position == idx)
+          {
+             sum += ((sd->horizontal) ? it->item->w : it->item->h);
+             idx += sd->nmax;
+          }
+     }
+   return sum;
+}
+
+static Eina_Bool
+_setup_custom_size_mode(Elm_Gengrid_Data *sd)
+{
+   unsigned int *tmp;
+   int alloc_size = sd->nmax * sizeof(unsigned int);
+   if (sd->nmax <= sd->custom_alloc_size) return EINA_TRUE;
+
+   tmp = realloc(sd->custom_size_sum, alloc_size);
+   if (!tmp) return EINA_FALSE;
+   sd->custom_size_sum = tmp;
+
+   tmp = realloc(sd->custom_tot_sum, alloc_size);
+   if (!tmp) return EINA_FALSE;
+   sd->custom_tot_sum = tmp;
+
+   sd->custom_alloc_size = sd->nmax;
+   return EINA_TRUE;
+}
+
+static inline void
+_cleanup_custom_size_mode(Elm_Gengrid_Data *sd)
+{
+   ELM_SAFE_FREE(sd->custom_size_sum, free);
+   ELM_SAFE_FREE(sd->custom_tot_sum, free);
+}
+
+static void
+_custom_size_mode_calc(Elm_Gengrid_Data *sd)
+{
+   unsigned int i, max;
+   if (!sd->custom_tot_sum) return;
+
+   max = sd->custom_tot_sum[0] = _get_item_span(sd, 0);
+   for (i = 1; i < sd->custom_alloc_size; ++i)
+     {
+        sd->custom_tot_sum[i] = _get_item_span(sd, i);
+        max = (max < sd->custom_tot_sum[i]) ? sd->custom_tot_sum[i] : max;
+     }
+   sd->custom_tot_max = max;
+}
+
 static Eina_Bool
 _is_no_select(Elm_Gen_Item *it)
 {
@@ -286,6 +346,38 @@ _is_no_select(Elm_Gen_Item *it)
    return EINA_FALSE;
 }
 
+EOLIAN static void
+_elm_gengrid_item_custom_size_get(Eo *eo_it EINA_UNUSED,
+                                   Elm_Gen_Item *it,
+                                   Evas_Coord *w,
+                                   Evas_Coord *h)
+{
+   ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
+
+   if (w) *w = GG_IT(it)->w;
+   if (h) *h = GG_IT(it)->h;
+}
+
+EOLIAN static void
+_elm_gengrid_item_custom_size_set(Eo *eo_it EINA_UNUSED,
+                         Elm_Gen_Item *it,
+                         Evas_Coord w,
+                         Evas_Coord h)
+{
+   ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
+   ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
+
+   if (!sd->custom_size_mode) sd->custom_size_mode = !sd->custom_size_mode;
+   if ((GG_IT(it)->w == w) && (GG_IT(it)->h == h)) return;
+   GG_IT(it)->h = h;
+   GG_IT(it)->w = w;
+
+   //TIZEN_ONLY(20160511) : Remove job for fixing calculate timing issue.
+   evas_object_smart_changed(sd->pan_obj);
+   //ecore_job_del(sd->calc_job);
+   //sd->calc_job = ecore_job_add(_calc_job, sd->obj);
+}
+
 EOLIAN static Elm_Object_Item *
 _elm_gengrid_search_by_text_item_get(Eo *obj EINA_UNUSED,
                                      Elm_Gengrid_Data *sd,
@@ -333,80 +425,160 @@ static void
 _item_show_region(void *data)
 {
    Elm_Gengrid_Data *sd = data;
-   Evas_Coord cvw, cvh, it_xpos = 0, it_ypos = 0, minx = 0, miny = 0;
+   Evas_Coord cvw, cvh, it_xpos = 0, it_ypos = 0, minx = 0, miny = 0, row = 0, col = 0;
    Evas_Coord vw = 0, vh = 0;
    Elm_Object_Item *eo_it = NULL;
+   Eina_Bool was_resized = EINA_FALSE;
    evas_object_geometry_get(sd->pan_obj, NULL, NULL, &cvw, &cvh);
 
    if ((cvw != 0) && (cvh != 0))
-       {
-          if (sd->show_region)
-            eo_it = sd->show_it;
-          else if (sd->bring_in)
-            eo_it = sd->bring_in_it;
+     {
+        int x = 0, y = 0;
+        if (sd->show_region)
+          eo_it = sd->show_it;
+        else if (sd->bring_in)
+          eo_it = sd->bring_in_it;
 
-          if (!eo_it) return;
-          ELM_GENGRID_ITEM_DATA_GET(eo_it, it);
+        if (!eo_it) return;
+        ELM_GENGRID_ITEM_DATA_GET(eo_it, it);
 
-          eo_do(sd->pan_obj, elm_obj_pan_pos_min_get(&minx, &miny));
-          if (sd->horizontal && (sd->item_height > 0))
-            {
-               if (it->x >= 1)
-                 it_xpos = ((it->x - GG_IT(it)->prev_group) * sd->item_width)
-                    + (GG_IT(it)->prev_group * sd->group_item_width)
-                    + minx;
-               else it_xpos = minx;
-               it_ypos = it->y * sd->item_height + miny;
-            }
-          else if (sd->item_width > 0)
-            {
-               it_xpos = it->x * sd->item_width + minx;
-               if (it->y >= 1)
-                 it_ypos = ((it->y - GG_IT(it)->prev_group) * sd->item_height)
-                    + (GG_IT(it)->prev_group * sd->group_item_height)
-                    + miny;
-               else it_ypos = miny;
-            }
+        eo_do(sd->pan_obj, elm_obj_pan_pos_min_get(&minx, &miny));
+        if (sd->horizontal && (sd->item_height > 0))
+          {
+             row = cvh / sd->item_height;
+             if (row <= 0) row = 1;
+             x = (it->position - 1) / row;
+             y = (it->position - 1) % row;
+             was_resized = sd->custom_size_mode && (y < (Evas_Coord)sd->custom_alloc_size);
+             if (was_resized)
+               {
+                  it_xpos = GG_IT(it)->sw
+                     + ((sd->custom_tot_max - sd->custom_tot_sum[y]) * sd->align_x)
+                     + (GG_IT(it)->prev_group * sd->group_item_width)
+                     + minx;
+               }
+             else
+               {
+                  col = sd->item_count / row;
+                  if (elm_widget_mirrored_get(sd->obj))
+                    {
+                       if (sd->item_count % row == 0)
+                         x = col - 1 - x;
+                       else
+                         x = col - x;
+                    }
+                  if (x >= 1)
+                    {
+                       it_xpos = ((x - GG_IT(it)->prev_group) * sd->item_width)
+                          + (GG_IT(it)->prev_group * sd->group_item_width)
+                          + minx;
+                    }
+                  else it_xpos = minx;
+                  /**
+                   * If custom size cannot be used for a row
+                   * account for offset due to rows which are
+                   * using custom sizes already.
+                   */
+                  if (sd->custom_alloc_size > 0)
+                    {
+                       if (sd->item_count % row)
+                         col++;
+                       it_xpos += (sd->custom_tot_max
+                          - ((col - GG_IT(it)->prev_group) * sd->item_width)
+                          + (GG_IT(it)->prev_group * sd->group_item_width)) * sd->align_x;
+                    }
+               }
 
-          switch (sd->scroll_to_type)
-            {
-               case ELM_GENGRID_ITEM_SCROLLTO_TOP:
-                  eo_do(WIDGET(it), elm_interface_scrollable_content_viewport_geometry_get
-                        (NULL, NULL, &vw, &vh));
-                  break;
-               case ELM_GENGRID_ITEM_SCROLLTO_MIDDLE:
-                  eo_do(WIDGET(it), elm_interface_scrollable_content_viewport_geometry_get
-                        (NULL, NULL, &vw, &vh));
-                  it_xpos = it_xpos - ((vw - sd->item_width) / 2);
-                  it_ypos = it_ypos - ((vh - sd->item_height) / 2);
-                  break;
-               // @tizen_feature
-               case ELM_GENGRID_ITEM_SCROLLTO_BOTTOM:
-                  eo_do(WIDGET(it), elm_interface_scrollable_content_viewport_geometry_get
-                        (NULL, NULL, &vw, &vh));
-                  it_xpos = it_xpos - vw + sd->item_width;
-                  it_ypos = it_ypos - vh + sd->item_height;
-                  break;
-               ///
-               default:
-                  vw = sd->item_width;
-                  vh = sd->item_height;
-                  break;
-            }
+             miny = miny + ((cvh - (sd->item_height * row))
+                  * sd->align_y);
+             it_ypos = y * sd->item_height + miny;
+             it->x = x;
+             it->y = y;
+          }
+        else if (sd->item_width > 0)
+          {
+             col = cvw / sd->item_width;
+             if (col <= 0) col = 1;
+             y = (it->position - 1) / col;
+             x = (it->position - 1) % col;
+             was_resized = x < (Evas_Coord)sd->custom_alloc_size;
+             if (was_resized)
+               {
+                  it_ypos = GG_IT(it)->sh
+                     + ((sd->custom_tot_max - sd->custom_tot_sum[x]) * sd->align_y)
+                     + (GG_IT(it)->prev_group * sd->group_item_height)
+                     + miny;
+               }
+             else
+               {
+                  if (y >= 1)
+                    {
+                       it_ypos = ((y - GG_IT(it)->prev_group) * sd->item_height)
+                          + (GG_IT(it)->prev_group * sd->group_item_height)
+                          + miny;
+                    }
+                  else it_ypos = miny;
+                  /**
+                   * If custom size cannot be used for a column
+                   * account for offset due to columns which are
+                   * using custom sizes already.
+                   */
+                  if (sd->custom_alloc_size > 0)
+                    {
+                       row = sd->item_count / col;
+                       if (sd->item_count % col)
+                         row++;
+                       it_ypos += (sd->custom_tot_max
+                          - ((row - GG_IT(it)->prev_group) * sd->item_height)
+                          + (GG_IT(it)->prev_group * sd->group_item_height)) * sd->align_y;
+                    }
+               }
+             minx = minx + ((cvw - (sd->item_width * col))
+                  * sd->align_x);
+             it_xpos = x * sd->item_width + minx;
+             it->x = x;
+             it->y = y;
+          }
 
-          if (sd->show_region)
-            {
-               eo_do(WIDGET(it), elm_interface_scrollable_content_region_show(
-                                                     it_xpos, it_ypos, vw, vh));
-               sd->show_region = EINA_FALSE;
-            }
-          if (sd->bring_in)
-            {
-               eo_do(WIDGET(it), elm_interface_scrollable_region_bring_in(
-                                                 it_xpos, it_ypos, vw, vh));
-               sd->bring_in = EINA_FALSE;
-            }
-       }
+        switch (sd->scroll_to_type)
+          {
+           case ELM_GENGRID_ITEM_SCROLLTO_TOP:
+              eo_do(WIDGET(it), elm_interface_scrollable_content_viewport_geometry_get
+                    (NULL, NULL, &vw, &vh));
+              break;
+           case ELM_GENGRID_ITEM_SCROLLTO_MIDDLE:
+              eo_do(WIDGET(it), elm_interface_scrollable_content_viewport_geometry_get
+                    (NULL, NULL, &vw, &vh));
+              it_xpos = it_xpos - ((vw - sd->item_width) / 2);
+              it_ypos = it_ypos - ((vh - sd->item_height) / 2);
+              break;
+              // @tizen_feature
+           case ELM_GENGRID_ITEM_SCROLLTO_BOTTOM:
+              eo_do(WIDGET(it), elm_interface_scrollable_content_viewport_geometry_get
+                    (NULL, NULL, &vw, &vh));
+              it_xpos = it_xpos - vw + sd->item_width;
+              it_ypos = it_ypos - vh + sd->item_height;
+              break;
+              ///
+           default:
+              vw = (sd->horizontal && was_resized) ? GG_IT(it)->w : sd->item_width;
+              vh = (!sd->horizontal && was_resized) ? GG_IT(it)->h : sd->item_height;
+              break;
+          }
+
+        if (sd->show_region)
+          {
+             eo_do(WIDGET(it), elm_interface_scrollable_content_region_show(
+                   it_xpos, it_ypos, vw, vh));
+             sd->show_region = EINA_FALSE;
+          }
+        if (sd->bring_in)
+          {
+             eo_do(WIDGET(it), elm_interface_scrollable_region_bring_in(
+                   it_xpos, it_ypos, vw, vh));
+             sd->bring_in = EINA_FALSE;
+          }
+     }
 }
 
 //TIZEN_ONLY(20160511) : Remove job for fixing calculate timing issue.
@@ -447,6 +619,15 @@ _calc(void *data)
         if (nmax < 1)
           nmax = 1;
 
+        sd->nmax = nmax;
+        if (sd->custom_size_mode)
+          {
+             if (!_setup_custom_size_mode(sd))
+               ERR("Failed to allocate memory for custom item size "
+                   "calculations!: gengrid=%p", sd->obj);
+             _custom_size_mode_calc(sd);
+          }
+
         EINA_INLIST_FOREACH(sd->items, it)
           {
              if (GG_IT(it)->prev_group != count_group)
@@ -470,15 +651,23 @@ _calc(void *data)
         count = sd->item_count + sd->items_lost - count_group;
         if (sd->horizontal)
           {
-             minw = (ceil(count / (float)nmax) * sd->item_width) +
-               (count_group * sd->group_item_width);
              minh = nmax * sd->item_height;
+             if (sd->custom_size_mode && (sd->custom_alloc_size > 0))
+               minw = sd->custom_tot_max +
+                  (count_group * sd->group_item_width);
+             else
+               minw = (ceil(count / (float)nmax) * sd->item_width) +
+                  (count_group * sd->group_item_width);
           }
         else
           {
              minw = nmax * sd->item_width;
-             minh = (ceil(count / (float)nmax) * sd->item_height) +
-               (count_group * sd->group_item_height);
+             if (sd->custom_size_mode && (sd->custom_alloc_size > 0))
+               minh = sd->custom_tot_max +
+                  (count_group * sd->group_item_height);
+             else
+               minh = (ceil(count / (float)nmax) * sd->item_height) +
+                  (count_group * sd->group_item_height);
           }
 
         if ((minw != sd->minw) || (minh != sd->minh))
@@ -490,7 +679,6 @@ _calc(void *data)
           }
 
         sd->nmax = nmax;
-
         //TIZEN_ONLY(20160511) : Remove job for fixing calculate timing issue.
         //evas_object_smart_changed(sd->pan_obj);
         //
@@ -1570,7 +1758,7 @@ _item_place(Elm_Gen_Item *it,
    Evas_Coord x, y, ox, oy, cvx, cvy, cvw, cvh, iw, ih, ww;
    Evas_Coord tch, tcw, alignw = 0, alignh = 0, vw, vh;
    Eina_Bool reorder_item_move_forward = EINA_FALSE;
-   Eina_Bool was_realized;
+   Eina_Bool was_realized, can_resize;
    Elm_Gen_Item_Type *item;
    long items_count;
    int item_pos;
@@ -1603,8 +1791,14 @@ _item_place(Elm_Gen_Item *it,
         if (items_count % items_visible)
           columns++;
 
-        tcw = (wsd->item_width * columns) + (wsd->group_item_width *
-                                             eina_list_count(wsd->group_items));
+        /* If custom sizes cannot be applied to items
+         * of a row use default item size. */
+        can_resize = (wsd->custom_size_mode && (cy < (Evas_Coord)wsd->custom_alloc_size));
+        if (can_resize)
+          tcw = wsd->custom_tot_sum[cy];
+        else
+          tcw = (wsd->item_width * columns) + (wsd->group_item_width *
+                                               eina_list_count(wsd->group_items));
         alignw = (vw - tcw) * wsd->align_x;
 
         items_row = items_visible;
@@ -1636,8 +1830,14 @@ _item_place(Elm_Gen_Item *it,
         if (items_count % items_visible)
           rows++;
 
-        tch = (wsd->item_height * rows) + (wsd->group_item_height *
-                                           eina_list_count(wsd->group_items));
+        /* If custom sizes cannot be applied to items
+         * of a column use to default item size. */
+        can_resize = (wsd->custom_size_mode && (cx < (Evas_Coord)wsd->custom_alloc_size));
+        if (can_resize)
+          tch = wsd->custom_tot_sum[cx];
+        else
+          tch = (wsd->item_height * rows) + (wsd->group_item_height *
+                                             eina_list_count(wsd->group_items));
         alignh = (vh - tch) * wsd->align_y;
 
         items_col = items_visible;
@@ -1684,29 +1884,63 @@ _item_place(Elm_Gen_Item *it,
      {
         if (wsd->horizontal)
           {
-             x = (((cx - item->prev_group) * wsd->item_width)
-                  + (item->prev_group * wsd->group_item_width)) -
-               wsd->pan_x + ox + alignw;
+             if (can_resize)
+               {
+                  if (cx == 0) wsd->custom_size_sum[cy] = 0;
+                  x = ((item->prev_group * wsd->item_width)
+                       + (item->prev_group * wsd->group_item_width)) -
+                     wsd->pan_x + ox + alignw + wsd->custom_size_sum[cy];
+
+                  if (elm_widget_mirrored_get(WIDGET(it)))
+                    it->item->sw = wsd->custom_tot_sum[cy] - wsd->custom_size_sum[cy] - it->item->w;
+                  else
+                    it->item->sw = wsd->custom_size_sum[cy];
+
+                  wsd->custom_size_sum[cy] += it->item->w;
+               }
+             else
+               {
+                  x = (((cx - item->prev_group) * wsd->item_width)
+                       + (item->prev_group * wsd->group_item_width)) -
+                     wsd->pan_x + ox + alignw;
+               }
              y = (cy * wsd->item_height) - wsd->pan_y + oy + alignh;
           }
         else
           {
+             if (can_resize)
+               {
+                  if (cy == 0) wsd->custom_size_sum[cx] = 0;
+                  y = ((item->prev_group * wsd->item_height)
+                       + (item->prev_group * wsd->group_item_height)) -
+                     wsd->pan_y + oy + alignh + wsd->custom_size_sum[cx];
+
+                  it->item->sh = wsd->custom_size_sum[cx];
+                  wsd->custom_size_sum[cx] += it->item->h;
+               }
+             else
+               {
+                  y = (((cy - item->prev_group)
+                        * wsd->item_height) + (item->prev_group *
+                                               wsd->group_item_height)) -
+                     wsd->pan_y + oy + alignh;
+               }
              x = (cx * wsd->item_width) - wsd->pan_x + ox + alignw;
-             y = (((cy - item->prev_group)
-                   * wsd->item_height) + (item->prev_group *
-                                          wsd->group_item_height)) -
-               wsd->pan_y + oy + alignh;
           }
+
         if (elm_widget_mirrored_get(WIDGET(it))) /* Switch items side
                                                   * and componsate for
                                                   * pan_x when in RTL
                                                   * mode */
           {
              evas_object_geometry_get(WIDGET(it), NULL, NULL, &ww, NULL);
-             x = ww - x - wsd->item_width - wsd->pan_x - wsd->pan_x + ox + ox;
+             if (wsd->horizontal && can_resize)
+               x = ww - x - it->item->w - wsd->pan_x - wsd->pan_x + ox + ox;
+             else
+               x = ww - x - wsd->item_width - wsd->pan_x - wsd->pan_x + ox + ox;
           }
-        iw = wsd->item_width;
-        ih = wsd->item_height;
+        iw = (wsd->horizontal && can_resize) ? it->item->w : wsd->item_width;
+        ih = (!wsd->horizontal && can_resize) ? it->item->h : wsd->item_height;
      }
 
    was_realized = it->realized;
@@ -1726,8 +1960,12 @@ _item_place(Elm_Gen_Item *it,
                {
                   if (it->parent->item->gx < ox)
                     {
-                       it->parent->item->gx = x + wsd->item_width -
-                         wsd->group_item_width;
+                       if (wsd->custom_size_mode)
+                         it->parent->item->gx = x + it->item->w -
+                           wsd->group_item_width;
+                       else
+                         it->parent->item->gx = x + wsd->item_width -
+                           wsd->group_item_width;
                        if (it->parent->item->gx > ox)
                          it->parent->item->gx = ox;
                     }
@@ -1737,8 +1975,12 @@ _item_place(Elm_Gen_Item *it,
                {
                   if (it->parent->item->gy < oy)
                     {
-                       it->parent->item->gy = y + wsd->item_height -
-                         wsd->group_item_height;
+                       if (wsd->custom_size_mode)
+                         it->parent->item->gy = y + it->item->h -
+                           wsd->group_item_height;
+                       else
+                         it->parent->item->gy = y + wsd->item_height -
+                           wsd->group_item_height;
                        if (it->parent->item->gy > oy)
                          it->parent->item->gy = oy;
                     }
@@ -2581,7 +2823,7 @@ _elm_gengrid_item_edge_check(Elm_Object_Item *eo_it,
           {
              ELM_GENGRID_ITEM_DATA_GET(eo_item, item);
              evas_object_geometry_get(VIEW(item), &cx, &cy, NULL, NULL);
-             if ((sd->horizontal) && (ix == cx) && (iy > cy))
+             if ((sd->horizontal) && (iy > cy))
                return EINA_FALSE;
              else if ((!sd->horizontal) && (iy == cy))
                {
@@ -2609,7 +2851,7 @@ _elm_gengrid_item_edge_check(Elm_Object_Item *eo_it,
           {
              ELM_GENGRID_ITEM_DATA_GET(eo_item, item);
              evas_object_geometry_get(VIEW(item), &cx, &cy, NULL, NULL);
-             if ((sd->horizontal) && (ix == cx) && (iy < cy))
+             if ((sd->horizontal) && (iy < cy))
                return EINA_FALSE;
              else if ((!sd->horizontal) && (iy == cy))
                {
@@ -4344,6 +4586,10 @@ _elm_gengrid_item_new(Elm_Gengrid_Data *sd,
    GG_IT(it) = ELM_NEW(Elm_Gen_Item_Type);
    GG_IT(it)->wsd = sd;
 
+   /* for non homogenous items */
+   it->item->w = sd->item_width;
+   it->item->h = sd->item_height;
+
    it->group = it->itc->item_style &&
      (!strcmp(it->itc->item_style, "group_index"));
    sd->item_count++;
@@ -4430,6 +4676,12 @@ _elm_gengrid_evas_object_smart_add(Eo *obj, Elm_Gengrid_Data *priv)
    evas_object_raise(priv->stack);
 
    eo_do(obj, elm_interface_scrollable_extern_pan_set(priv->pan_obj));
+
+   /* for non homogenous mode */
+   priv->custom_size_mode = EINA_FALSE;
+   priv->custom_size_sum = NULL;
+   priv->custom_tot_sum = NULL;
+   priv->custom_alloc_size = 0;
 }
 
 EOLIAN static void
@@ -4438,6 +4690,7 @@ _elm_gengrid_evas_object_smart_del(Eo *obj, Elm_Gengrid_Data *sd)
    elm_gengrid_clear(obj);
    ELM_SAFE_FREE(sd->pan_obj, evas_object_del);
    ELM_SAFE_FREE(sd->stack, evas_object_del);
+   _cleanup_custom_size_mode(sd);
 
    _item_cache_zero(sd);
 
index c8b0507938f4d630a1ed088a13d94e766194e07a..eb58bdf1821e2f71167d98820d5ddce4175f9f5e 100644 (file)
@@ -177,7 +177,7 @@ class Elm.Gengrid_Item(Elm.Widget_Item)
                    ]]
                 }
                 values {
-                     mode: Elm.Object.Select_Mode(Elm.Object.Select_Mode.max); [[The selected mode]]
+                     Mode: Elm.Object.Select_Mode(Elm.Object.Select_Mode.max); [[The selected mode]]
                 }
            }
            /*      init { FIXME
@@ -290,6 +290,32 @@ class Elm.Gengrid_Item(Elm.Widget_Item)
                      @out l: own(list<own(Evas.Object *)> *); [[The contents list to return.]]
                 }
            }
+           @property custom_size {
+                get @internal {
+                     [[Get the dimensions of a gengrid item.
+
+                       Gives the dimensions set with elm_gengrid_item_custom_size_set(). If the item
+                       has not been modified values set with elm_gengrid_item_size_set() are obtained.
+
+                       @since 1.17]]
+                }
+                set @internal {
+                     [[Resize dimensions of a gengrid item.
+
+                       In case of a horizontal grid, only the widths only be resized and
+                       in case of vertical only the heights can be resized. Item size
+                       should be set by elm_gengrid_item_size_set() beforehand.
+
+                       The values set by elm_gengrid_item_size_set() will be used for the
+                       dimension that remains fixed.
+
+                       @since 1.17]]
+                }
+                values {
+                     w: Evas_Coord; [[The item's width.]]
+                     h: Evas_Coord; [[The item's height.]]
+                }
+           }
       }
       implements {
            Eo.Base.constructor;
index bef99fb7a0b4d0aa35b3a363551d8dc9da68cd29..cab2334c775b953bad55277e11c232a92d09c325 100644 (file)
@@ -150,6 +150,16 @@ struct _Elm_Gengrid_Data
    Evas_Coord                            top_to_x, top_to_y;
    Eina_Bool                             is_append : 1;
    //
+   /* custom dimensions may be set for any item.
+    * the logic for placing items requires that either item widths
+    * for horizontal gengrid or item height for vertical gengrid
+    * may be varied at once. */
+
+   Eina_Bool                          custom_size_mode : 1; /* a flag that items have custom sizes */
+   unsigned int                       *custom_size_sum; /* array to store sum of the widths for items placed already for each row or sum of heights for each column. this is to find location of next item. */
+   unsigned int                       *custom_tot_sum; /* array to store total sum of all widths or heights. this is used for item alignment calculations. */
+   unsigned int                       custom_tot_max; /* maximum of the total sums over all rows or columns. this is also used for item alignment calculations. */
+   unsigned int                       custom_alloc_size; /* amount of memory allocated to above dynamic arrays in terms of number of rows or columns. */
 };
 
 struct Elm_Gen_Item_Type
@@ -168,6 +178,9 @@ struct Elm_Gen_Item_Type
    Eina_Bool               nocache_once : 1; /* do not use cache for
                                               * this item only once */
    Eina_Bool               nocache : 1; /* do not use cache for this item */
+
+   /* for non homogenous items */
+   Evas_Coord              w, h, sw, sh;
 };
 
 typedef struct _Item_Cache Item_Cache;