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; --