sanghyeonlee pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=73095ad7ad7cf67c2c9a66787da6395bfbdd3e4a

commit 73095ad7ad7cf67c2c9a66787da6395bfbdd3e4a
Author: SangHyeon Lee <sh10233....@samsung.com>
Date:   Wed Oct 5 15:36:04 2016 +0900

    gengrid: support for non homogenous items
    
    Summary:
    Dimensions of gengrid items can be altered for
    non homogenity.
    
    Care must be taken however to set the homogenous
    size for items using elm_gengrid_item_size_set().
    
    In horizontal mode only the heights will change
    and in vertical mode only the widths. Fixed dimension
    will be as set with elm_gengrid_item_size_set().
    
    This is forked by https://phab.enlightenment.org/D2422
    
    Test Plan:
    elementary_test -to "Gengrid Resized Items"
    Current test program provides focus autoscroll
    and item looping options.
    
    Reviewers: raster
    
    Subscribers: cedric, jpeg
    
    Differential Revision: https://phab.enlightenment.org/D4330
---
 src/bin/elementary/test.c               |   2 +
 src/bin/elementary/test_gengrid.c       | 208 +++++++++++++++++++++
 src/lib/elementary/elm_gengrid.c        | 317 ++++++++++++++++++++++++++++----
 src/lib/elementary/elm_gengrid_item.eo  |  27 +++
 src/lib/elementary/elm_widget_gengrid.h |  14 ++
 5 files changed, 531 insertions(+), 37 deletions(-)

diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c
index 2c3d476..a4ca08b 100644
--- a/src/bin/elementary/test.c
+++ b/src/bin/elementary/test.c
@@ -156,6 +156,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);
@@ -803,6 +804,7 @@ add_tests:
    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 Disabled Item Focus", 
test_gengrid_disabled_item_focus);
+   ADD_TEST(NULL, "Lists - Gengrid", "GenGrid Item Custom Size", 
test_gengrid_item_custom_size);
 
    //------------------------------//
    ADD_TEST(NULL, "General", "Scaling", test_scaling);
diff --git a/src/bin/elementary/test_gengrid.c 
b/src/bin/elementary/test_gengrid.c
index 2c1ea55..da25680 100644
--- a/src/bin/elementary/test_gengrid.c
+++ b/src/bin/elementary/test_gengrid.c
@@ -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;
@@ -2336,3 +2338,209 @@ 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);
+}
+
diff --git a/src/lib/elementary/elm_gengrid.c b/src/lib/elementary/elm_gengrid.c
index ed7ba99..717b306 100644
--- a/src/lib/elementary/elm_gengrid.c
+++ b/src/lib/elementary/elm_gengrid.c
@@ -94,7 +94,7 @@ static Eina_Bool _key_action_escape(Evas_Object *obj, const 
char *params);
 static void _item_position_update(Eina_Inlist *list, int idx);
 static void _item_mouse_callbacks_add(Elm_Gen_Item *it, Evas_Object *view);
 static void _item_mouse_callbacks_del(Elm_Gen_Item *it, Evas_Object *view);
-
+static void _calc_job(void *data);
 
 static const Elm_Action key_actions[] = {
    {"move", _key_action_move},
@@ -264,6 +264,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)
 {
@@ -277,6 +337,36 @@ _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;
+
+   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,
@@ -324,13 +414,15 @@ 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, col = 0, row = 0, minx = 0, 
miny = 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))
        {
+          int x = 0;
           if (sd->show_region)
             eo_it = sd->show_it;
           else if (sd->bring_in)
@@ -342,21 +434,91 @@ _item_show_region(void *data)
           elm_obj_pan_pos_min_get(sd->pan_obj, &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;
+               row = cvh / sd->item_height;
+               if (row <= 0) row = 1;
+               was_resized = sd->custom_size_mode && (it->y < 
(Evas_Coord)sd->custom_alloc_size);
+               if (was_resized)
+                 {
+                    it_xpos = GG_IT(it)->sw
+                       + ((sd->custom_tot_max - sd->custom_tot_sum[it->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 - it->x;
+                         else
+                           x = col - it->x;
+                      }
+                    else x = it->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;
+                      }
+                 }
+               miny = miny + ((cvh - (sd->item_height * row))
+                    * sd->align_y);
                it_ypos = it->y * sd->item_height + miny;
             }
           else if (sd->item_width > 0)
             {
+               col = cvw / sd->item_width;
+               if (col <= 0) col = 1;
+               was_resized = it->x < (Evas_Coord)sd->custom_alloc_size;
+               if (was_resized)
+                 {
+                    it_ypos = GG_IT(it)->sh
+                       + ((sd->custom_tot_max - sd->custom_tot_sum[it->x]) * 
sd->align_y)
+                       + (GG_IT(it)->prev_group * sd->group_item_height)
+                       + miny;
+                 }
+               else
+                 {
+                    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;
+                    /**
+                     * 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 = 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;
             }
 
           switch (sd->scroll_to_type)
@@ -378,8 +540,8 @@ _item_show_region(void *data)
                   it_ypos = it_ypos - vh + sd->item_height;
                   break;
                default:
-                  vw = sd->item_width;
-                  vh = sd->item_height;
+                  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;
             }
 
@@ -419,6 +581,15 @@ _calc_job(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)
@@ -442,15 +613,23 @@ _calc_job(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))
@@ -1497,7 +1676,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;
@@ -1530,8 +1709,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;
@@ -1563,8 +1748,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;
@@ -1611,18 +1802,48 @@ _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
@@ -1630,10 +1851,13 @@ _item_place(Elm_Gen_Item *it,
                                                   * 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;
@@ -1652,8 +1876,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;
                     }
@@ -1663,8 +1891,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;
                     }
@@ -4243,6 +4475,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++;
@@ -4321,6 +4557,12 @@ _elm_gengrid_efl_canvas_group_group_add(Eo *obj, 
Elm_Gengrid_Data *priv)
    evas_object_raise(priv->stack);
 
    elm_interface_scrollable_extern_pan_set(obj, 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
@@ -4329,6 +4571,7 @@ _elm_gengrid_efl_canvas_group_group_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);
    ecore_job_del(sd->calc_job);
diff --git a/src/lib/elementary/elm_gengrid_item.eo 
b/src/lib/elementary/elm_gengrid_item.eo
index 70ff7cd..c740ccc 100644
--- a/src/lib/elementary/elm_gengrid_item.eo
+++ b/src/lib/elementary/elm_gengrid_item.eo
@@ -129,6 +129,33 @@ class Elm.Gengrid.Item(Elm.Widget.Item)
                      mode: Elm.Object.Select_Mode(Elm.Object.Select_Mode.max); 
[[The selected mode]]
                 }
            }
+           @property custom_size {
+                [[Custom size mode for non-homogeneous gengrid. ]]
+                get {
+                     [[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.19]]
+                }
+                set {
+                     [[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.19]]
+                }
+                values {
+                     w : Evas.Coord; [[The item's width.]]
+                     h : Evas.Coord; [[The item's height.]]
+                }
+           }
            /*      init { FIXME
                    params {
                    Evas_Smart_Cb func;
diff --git a/src/lib/elementary/elm_widget_gengrid.h 
b/src/lib/elementary/elm_widget_gengrid.h
index 20df266..6f28c38 100644
--- a/src/lib/elementary/elm_widget_gengrid.h
+++ b/src/lib/elementary/elm_widget_gengrid.h
@@ -135,6 +135,17 @@ struct _Elm_Gengrid_Data
                                                       * cache. */
    int                                   item_cache_count;
    int                                   item_cache_max;
+
+   /* 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
@@ -153,6 +164,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;

-- 


Reply via email to