From 4b5304d7f2b400064c0896f7510f31850912e5af Mon Sep 17 00:00:00 2001 From: SangHyeon Jade Lee Date: Tue, 20 Nov 2018 14:32:31 +0900 Subject: [PATCH] efl_ui_grid : introduce new packable grid widget for Efl.Ui.Widget Summary: Introduce new packable grid for Efl.Ui.Widget toolkits. most of parts are same as Efl.Ui.List, and it also support Efl.Pack_Linear, although it will not support Efl.Pack_Table, because item must be arranged sequential orders. Test Plan: We will make the tests on efl ui test suite. please test by make check. Reviewers: Hermet, cedric, felipealmeida, eagleeye, woohyun Reviewed By: Hermet, eagleeye Subscribers: CHAN, bu5hm4n, cedric Tags: #efl Differential Revision: https://phab.enlightenment.org/D6985 --- data/elementary/themes/default.edc | 1 + data/elementary/themes/edc/efl/grid.edc | 269 ++++ src/Makefile_Elementary.am | 13 +- .../elementary/efl_ui_grid_example_1.c | 104 ++ src/lib/elementary/Elementary.h | 5 + src/lib/elementary/efl_ui_grid.c | 1315 +++++++++++++++++ src/lib/elementary/efl_ui_grid.eo | 96 ++ src/lib/elementary/efl_ui_grid_default_item.c | 112 ++ .../elementary/efl_ui_grid_default_item.eo | 28 + .../efl_ui_grid_default_item_part_end.eo | 9 + .../efl_ui_grid_default_item_part_icon.eo | 9 + src/lib/elementary/efl_ui_grid_item.c | 83 ++ src/lib/elementary/efl_ui_grid_item.eo | 12 + src/lib/elementary/efl_ui_grid_item_private.h | 41 + src/lib/elementary/efl_ui_grid_private.h | 83 ++ .../efl_ui_list_default_item_part_icon.eo | 2 +- src/lib/elementary/meson.build | 10 + src/tests/elementary/efl_ui_test_grid.c | 338 +++++ src/tests/elementary/elm_suite.c | 4 + src/tests/elementary/elm_suite.h | 4 + src/tests/elementary/meson.build | 3 +- 21 files changed, 2538 insertions(+), 3 deletions(-) create mode 100644 data/elementary/themes/edc/efl/grid.edc create mode 100644 src/examples/elementary/efl_ui_grid_example_1.c create mode 100644 src/lib/elementary/efl_ui_grid.c create mode 100644 src/lib/elementary/efl_ui_grid.eo create mode 100644 src/lib/elementary/efl_ui_grid_default_item.c create mode 100644 src/lib/elementary/efl_ui_grid_default_item.eo create mode 100644 src/lib/elementary/efl_ui_grid_default_item_part_end.eo create mode 100644 src/lib/elementary/efl_ui_grid_default_item_part_icon.eo create mode 100644 src/lib/elementary/efl_ui_grid_item.c create mode 100644 src/lib/elementary/efl_ui_grid_item.eo create mode 100644 src/lib/elementary/efl_ui_grid_item_private.h create mode 100644 src/lib/elementary/efl_ui_grid_private.h create mode 100644 src/tests/elementary/efl_ui_test_grid.c diff --git a/data/elementary/themes/default.edc b/data/elementary/themes/default.edc index 40d1920a07..d0e7126fd4 100644 --- a/data/elementary/themes/default.edc +++ b/data/elementary/themes/default.edc @@ -174,6 +174,7 @@ collections { // XXX: mobile mode needs invisible scrollers... make signals that do this #include "edc/efl/scroller.edc" #include "edc/efl/list.edc" +#include "edc/efl/grid.edc" // XXX: mobile mode needs different entry setup #include "edc/efl/text.edc" #include "edc/efl/frame.edc" diff --git a/data/elementary/themes/edc/efl/grid.edc b/data/elementary/themes/edc/efl/grid.edc new file mode 100644 index 0000000000..4fa1ee77ed --- /dev/null +++ b/data/elementary/themes/edc/efl/grid.edc @@ -0,0 +1,269 @@ +group { "efl/grid"; + inherit: "efl/scroller"; +} + +group { "efl/view_grid"; + inherit: "efl/grid"; +} + +group { "efl/grid_item"; + data.item: "selectraise" "on"; + data.item: "focusraise" "on"; + images.image: "bevel_dark_out.png" COMP; + images.image: "shadow_rounded_horiz.png" COMP; + images.image: "vgrad_med_dark.png" COMP; + images.image: "bevel_out.png" COMP; + images.image: "shine.png" COMP; + parts { + + // BASE PARTS // + rect { "event"; + desc { "default"; + color: 0 0 0 0; + } + desc { "disabled"; + inherit: "default"; + hid; + } + } + rect { "base"; mouse; + desc { "default"; + } + } + image { "bevel"; nomouse; + desc { "default"; + image.normal: "bevel_dark_out.png"; + image.border: 2 2 2 2; + image.middle: 0; + fill.smooth: 0; + } + } + image { "sel_shadow"; nomouse; + desc { "default"; + image.normal: "shadow_rounded_horiz.png"; + image.border: 0 0 9 9; + rel1.offset: 0 -4; + rel2.offset: -1 5; + fill.smooth: 0; + hid; + } + desc { "selected"; + inherit: "default"; + vis; + } + } + image { "sel_base"; nomouse; + desc { "default"; + image.normal: "vgrad_med_dark.png"; + fill.smooth: 0; + hid; + TILED_HORIZ(120) + } + desc { "selected"; + inherit: "default"; + vis; + } + } + image { "sel_bevel"; nomouse; + desc { "default"; + image.normal: "bevel_out.png"; + image.border: 2 2 2 2; + image.middle: 0; + fill.smooth: 0; + hid; + } + desc { "selected"; + inherit: "default"; + vis; + } + } + // BASE PARTS // + + // TEXT PARTS // + text { "efl.text"; nomouse; + effect: SHADOW BOTTOM; + scale: 1; + desc { "default"; + fixed: 0 1; + rel1.relative: 0.0 1.0; + rel1.offset: 5 -5; + rel2.relative: 1.0 1.0; + rel2.offset: -5 -5; + color: FN_COL_DEFAULT; + color_class: "grid_item"; + align: 0.5 1.0; + text { font: FN; size: 10; + min: 0 1; + align: 0.5 1.0; + text_class: "grid_item"; + } + } + desc { "selected"; + inherit: "default"; + hid; + } + desc { "disabled"; + inherit: "default"; + hid; + } + } + text { "label2"; nomouse; + effect: SHADOW BOTTOM; + scale: 1; + desc { "default"; + rel1.to: "efl.text"; + rel2.to: "efl.text"; + color: FN_COL_DISABLE; + color_class: "grid_item_disabled"; + text { font: FN; size: 10; + text_source: "efl.text"; + align: 0.5 1.0; + text_class: "grid_item"; + } + hid; + } + desc { "selected"; + inherit: "default"; + hid; + } + desc { "disabled"; + inherit: "default"; + vis; + } + } + text { "label3"; nomouse; + effect: GLOW; + scale: 1; + desc { "default"; + rel1.offset: -2 -2; + rel1.to: "efl.text"; + rel2.offset: 1 0; + rel2.to: "efl.text"; + color: FN_COL_HIGHLIGHT; + color_class: "grid_item_selected"; + text { font: FN; size: 10; + text_source: "efl.text"; + align: 0.5 1.0; + text_class: "grid_item"; + } + hid; + } + desc { "selected"; + inherit: "default"; + vis; + } + desc { "disabled"; + inherit: "default"; + hid; + } + } + // TEXT PARTS // + + // CONTENT PARTS // + rect { "icon_area"; + desc { "default"; + fixed: 1 0; + rel1.offset: 2 2; + rel2.to_y: "efl.text"; + rel2.relative: 1.0 0.0; + rel2.offset: -3 -3; + } + desc { "disabled"; + inherit: "default"; + color: 255 255 255 64; + } + } + swallow { "efl.icon"; + clip_to: "icon_area"; + desc { "default"; + rel1.to: "icon_area"; + rel2.to: "icon_area"; + } + } + swallow { "efl.end"; + clip_to: "icon_area"; + desc { "default"; + fixed: 1 1; + align: 1.0 0.0; + rel1.relative: 1.0 0.0; + rel1.offset: -3 2; + rel2.relative: 1.0 0.0; + rel2.offset: -3 2; + } + } + // CONTENT PARTS // + + // TOP PARTS // + image { "sel_shine"; nomouse; + desc { "default"; + image.normal: "shine.png"; + rel1.offset: 0 -2; + rel1.to: "sel_base"; + rel2.relative: 1.0 0.0; + rel2.offset: -1 2; + rel2.to: "sel_base"; + hid; + FIXED_SIZE(69, 5) + } + desc { "selected"; + inherit: "default"; + vis; + } + } + rect { "event_block"; + desc { "default"; + color: 0 0 0 0; + hid; + } + desc { "disabled"; + inherit: "default"; + vis; + } + } + // TOP PARTS // + } + programs { + program { + signal: "efl,state,selected"; source: "efl"; + action: STATE_SET "selected"; + target: "sel_shadow"; + target: "sel_base"; + target: "sel_bevel"; + target: "sel_shine"; + target: "efl.text"; + target: "label2"; + target: "label3"; + } + program { + signal: "efl,state,unselected"; source: "efl"; + action: STATE_SET "default"; + target: "sel_shadow"; + target: "sel_base"; + target: "sel_bevel"; + target: "sel_shine"; + target: "efl.text"; + target: "label2"; + target: "label3"; + } + program { + signal: "efl,state,disabled"; source: "efl"; + action: STATE_SET "disabled"; + target: "event"; + target: "event_block"; + target: "efl.text"; + target: "label2"; + target: "label3"; + target: "icon_area"; + } + program { + signal: "efl,state,enabled"; source: "efl"; + action: STATE_SET "default"; + target: "event"; + target: "event_block"; + target: "efl.text"; + target: "label2"; + target: "label3"; + target: "icon_area"; + } + } +} diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index dd05b9d21f..f41adcaca6 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -89,6 +89,11 @@ elm_public_eolian_files = \ lib/elementary/efl_ui_list_default_item.eo \ lib/elementary/efl_ui_list_empty_item.eo \ lib/elementary/efl_ui_list.eo \ + lib/elementary/efl_ui_grid_item.eo \ + lib/elementary/efl_ui_grid_default_item_part_icon.eo \ + lib/elementary/efl_ui_grid_default_item_part_end.eo \ + lib/elementary/efl_ui_grid_default_item.eo \ + lib/elementary/efl_ui_grid.eo \ lib/elementary/efl_ui_panes_part.eo \ lib/elementary/efl_ui_progressbar_part.eo \ lib/elementary/elm_slider.eo \ @@ -415,6 +420,8 @@ includesunstable_HEADERS = \ lib/elementary/efl_ui_item_private.h \ lib/elementary/efl_ui_list_item_private.h \ lib/elementary/efl_ui_list_private.h \ + lib/elementary/efl_ui_grid_item_private.h \ + lib/elementary/efl_ui_grid_private.h \ lib/elementary/efl_ui_list_view_private.h \ lib/elementary/efl_ui_list_view_seg_array.h \ lib/elementary/elm_widget_web.h \ @@ -844,6 +851,9 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/efl_ui_list_default_item.c \ lib/elementary/efl_ui_list_empty_item.c \ lib/elementary/efl_ui_list.c \ + lib/elementary/efl_ui_grid_item.c \ + lib/elementary/efl_ui_grid_default_item.c \ + lib/elementary/efl_ui_grid.c \ lib/elementary/efl_ui_list_view.c \ lib/elementary/efl_ui_list_view_precise_layouter.c \ lib/elementary/efl_ui_list_view_seg_array.c \ @@ -1566,7 +1576,8 @@ tests_elementary_elm_suite_SOURCES = \ tests/elementary/elm_test_focus_common.c \ tests/elementary/elm_test_focus_common.h \ tests/elementary/elm_test_focus.c \ - tests/elementary/elm_test_focus_sub.c + tests/elementary/elm_test_focus_sub.c \ + tests/elementary/efl_ui_test_grid.c tests_elementary_elm_suite_CPPFLAGS = \ -DELM_INTERNAL_API_ARGESFSDFEFC=1 \ diff --git a/src/examples/elementary/efl_ui_grid_example_1.c b/src/examples/elementary/efl_ui_grid_example_1.c new file mode 100644 index 0000000000..26bf850e68 --- /dev/null +++ b/src/examples/elementary/efl_ui_grid_example_1.c @@ -0,0 +1,104 @@ +// gcc -o efl_ui_grid_example_1 efl_ui_grid_example_1.c `pkg-config --cflags --libs elementary` + +#ifdef HAVE_CONFIG_H +#include "elementary_config.h" +#else +#define EFL_BETA_API_SUPPORT 1 +#define EFL_EO_API_SUPPORT 1 +#endif + +#include +#include +#include + +#define IMAX 500; + +typedef struct _Grid_Event_Data { + Eo *grid; + Eo *item; +} Grid_Event_Data; + +Eo * +EoGenerate(const Efl_Class *klass, Eo *parent, Efl_Ui_Dir dir) +{ + Eo* obj = efl_add(klass, parent); + if (dir != EFL_UI_DIR_DEFAULT) efl_ui_direction_set(obj, dir); + efl_gfx_size_hint_weight_set(obj, EFL_GFX_SIZE_HINT_EXPAND, EFL_GFX_SIZE_HINT_EXPAND); + efl_gfx_size_hint_align_set(obj, EFL_GFX_SIZE_HINT_FILL, EFL_GFX_SIZE_HINT_FILL); + return obj; +} + +EAPI_MAIN int +elm_main(int argc, char **argv) +{ + int itemmax = IMAX; + int i = 0; + if (argv[1]) itemmax = atoi(argv[1]); + Eo *win, *box, *bbx, *upbtn, *allbtn, *clrbtn; + Eo *grid, *gitem; + Grid_Event_Data *gd = calloc(sizeof(Grid_Event_Data *), 1); + + win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(), + efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC), + efl_text_set(efl_added, "Efl.Ui.Grid"), + efl_ui_win_autodel_set(efl_added, EINA_TRUE)); + + box = EoGenerate(EFL_UI_BOX_CLASS, win, EFL_UI_DIR_VERTICAL); + elm_win_resize_object_add(win, box); + + Eo *btn = efl_add(EFL_UI_BUTTON_CLASS, box); + efl_gfx_size_hint_weight_set(btn, 0.3, 0.3); + efl_gfx_size_hint_align_set(btn, EFL_GFX_SIZE_HINT_FILL, EFL_GFX_SIZE_HINT_FILL); + efl_text_set(btn, "BUTTON"); + efl_pack_end(box, btn); + + Eina_Bool horiz = 0; + // TEST#1 : Create Grid + gd->grid = grid = EoGenerate(EFL_UI_GRID_CLASS, box, (horiz ? EFL_UI_DIR_HORIZONTAL : EFL_UI_DIR_VERTICAL)); + efl_ui_grid_item_size_set(grid, EINA_SIZE2D(100, 120)); // 4X4 + efl_pack_padding_set(grid, 5.0, 5.0, EINA_TRUE); + efl_pack_align_set(grid, 0.5, 0.5); + efl_pack_end(box, grid); + + // TEST#2 : Set Item Default Size + + Efl_Ui_Grid_Item *target = NULL; + + for (i = 0; i < itemmax; i++) + { + int r = 0, g = 0, b = 0; + // TEST#3 : Create Grid Item + gitem = efl_add(EFL_UI_GRID_DEFAULT_ITEM_CLASS, grid); + if (i == 300) target = gitem; + if (i == 0) gd->item = gitem; + Eo *rect = evas_object_rectangle_add(evas_object_evas_get(win)); + switch (i % 5) + { + case 0: + r = 255; + break; + case 1: + g = 255; + break; + case 2: + b = 255; + break; + case 3: + r = g = b = 255; + break; + case 4: + r = g = b = 0; + break; + } + efl_gfx_color_set(rect, r, g, b, 255); + efl_content_set(gitem, rect); + // TEST#4 : Pack end + efl_pack_end(grid, gitem); + } + + efl_gfx_entity_size_set(win, EINA_SIZE2D(417, 600)); + + elm_run(); + return 0; +} +ELM_MAIN() diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h index 1c220a11a2..9bd33c4feb 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -334,6 +334,11 @@ typedef Eo Efl_Ui_Focus_Manager; # include # include # include +# include +# include +# include +# include +# include # include # include # include diff --git a/src/lib/elementary/efl_ui_grid.c b/src/lib/elementary/efl_ui_grid.c new file mode 100644 index 0000000000..e983708950 --- /dev/null +++ b/src/lib/elementary/efl_ui_grid.c @@ -0,0 +1,1315 @@ +#ifdef HAVE_CONFIG_H +#include "elementary_config.h" +#endif + +#define ELM_LAYOUT_PROTECTED +#define EFL_UI_SCROLL_MANAGER_PROTECTED +#define EFL_UI_SCROLLBAR_PROTECTED +#define EFL_UI_SCROLLBAR_BETA + +#include +#include "elm_priv.h" +#include "efl_ui_grid_private.h" +#include "efl_ui_item_private.h" +#include "efl_ui_grid_item_private.h" + +#define MY_CLASS EFL_UI_GRID_CLASS +#define MY_CLASS_PFX efl_ui_grid + +#define MY_CLASS_NAME "Efl.Ui.Grid" + +static void _grid_clear_internal(Eo *obj, Efl_Ui_Grid_Data *pd); +static void _grid_item_unpack_internal(Eo *obj, Efl_Ui_Grid_Data *pd, Efl_Ui_Grid_Item *item); + +static void +_need_update(Efl_Ui_Grid_Data *pd) +{ + pd->need_update = EINA_TRUE; + //group_calculate call + efl_canvas_group_change(pd->obj); +} + +static void +_relayout(Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd, Eina_Position2D pan) +{ + Eina_List *l; + Efl_Ui_Grid_Item *item; + Efl_Ui_Grid_Item_Data *prev; + Eina_Position2D ipos; + Eina_Position2D cur = {0, 0}; + int outer; + int count = 0; + Eina_Bool horiz = 0; + Eina_Size2D min, max; + + if (pd->dir == EFL_UI_DIR_HORIZONTAL) horiz = 1; + + if (!pd->linemax) + { + pd->linemax =(horiz ? + ((pd->geo.h + pd->item.pad.h) / (pd->item.size.h + pd->item.pad.h)) : + ((pd->geo.w + pd->item.pad.w) / (pd->item.size.w + pd->item.pad.w))); + if (!pd->linemax) pd->linemax = 1; + } + + + outer = (horiz ? + (pd->geo.h + pd->item.pad.h) - (pd->linemax * (pd->item.size.h + pd->item.pad.h)) : + (pd->geo.w + pd->item.pad.w) - (pd->linemax * (pd->item.size.w + pd->item.pad.w))); + // outer left top + outer = (horiz ? (outer * pd->item.align.h) : (outer * pd->item.align.w)); + outer = (horiz ? (outer + pd->geo.y) : (outer + pd->geo.x)); + + // Block? + EINA_LIST_FOREACH(pd->items, l, item) + { + EFL_UI_GRID_ITEM_DATA_GET(item, id); + + if (pd->need_update || id->update_me || id->update_begin) + { + // Index begin with zero value : + id->index = count; + if (id->update_me) id->update_me = EINA_FALSE; + if (id->update_begin) + { + id->update_begin = EINA_FALSE; + pd->need_update = EINA_TRUE; + } + if (horiz) + { + id->pos.row = (count % pd->linemax); + id->pos.col = (count / pd->linemax); + //Next Line + if (count == 0) + { + cur.x = pd->geo.x; + cur.y = outer; + } + else if (id->pos.row == 0)// ((cur.y + pd->item.pad.h + pd->item.size.h) > pd->geo.h) + { + cur.x = prev->geo.x + pd->item.size.w + pd->item.pad.w; + cur.y = outer; + } + else + { + //cur.x = cur.x; + cur.y = prev->geo.y + pd->item.size.h + pd->item.pad.h; + } + } + else + { + id->pos.row = (count / pd->linemax); + id->pos.col = (count % pd->linemax); + //Next Line + if (count == 0) + { + cur.x = outer; + cur.y = pd->geo.y; + } + else if (id->pos.col == 0)//((cur.x + pd->item.pad.w + pd->item.size.w) > pd->geo.w) + { + cur.x = outer; + cur.y = prev->geo.y + pd->item.size.h + pd->item.pad.h; + } + else + { + cur.x = prev->geo.x + pd->item.size.w + pd->item.pad.w; + //cur.y = cur.y; + } + } + + min = efl_gfx_size_hint_min_get(item); + max = efl_gfx_size_hint_max_get(item); + + if (pd->item.size.w < min.w) pd->item.size.w = min.w; + if (pd->item.size.h < min.h) pd->item.size.h = min.h; + if ((max.w > 0) && pd->item.size.w > max.w) pd->item.size.w = max.w; + if ((max.h > 0) && pd->item.size.h > max.h) pd->item.size.h = max.h; + + id->geo.x = cur.x; + id->geo.y = cur.y; + id->geo.w = pd->item.size.w; + id->geo.h = pd->item.size.h; + + + } + + ipos.x = id->geo.x - pan.x; + ipos.y = id->geo.y - pan.y; + + // + efl_gfx_entity_position_set(item, ipos); + efl_gfx_entity_size_set(item, id->geo.size); + //efl_gfx_size_hint_restricted_min_set(item, id->geo.size); + + prev = id; + count++; + } + + if (horiz) + pd->geo.w = cur.x + pd->item.size.w + pd->item.pad.w - pd->geo.x; + else + pd->geo.h = cur.y + pd->item.size.h + pd->item.pad.h - pd->geo.y; + + //efl_gfx_size_hint_restricted_min_set(pd->content, pd->geo.size); + efl_gfx_entity_size_set(pd->content, pd->geo.size); + + pd->need_update = EINA_FALSE; +} + +static void +_reposition(Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd, Eina_Position2D pan) +{ + Efl_Ui_Grid_Item *item; + Eina_List *l; + Eina_Position2D ipos; + + // Block? + EINA_LIST_FOREACH(pd->items, l, item) + { + EFL_UI_GRID_ITEM_DATA_GET(item, id); + + ipos.x = id->geo.x - pan.x; + ipos.y = id->geo.y - pan.y; + efl_gfx_entity_position_set(item, ipos); + efl_gfx_entity_size_set(item, id->geo.size); + //efl_gfx_size_hint_min_set(item, id->geo.size); + } + +} + +//Need to reimplements for grid +static void +_item_scroll_internal(Eo *obj, + Efl_Ui_Grid_Item *item, + double align, + Eina_Bool anim) +{ + EFL_UI_GRID_DATA_GET_OR_RETURN(obj, pd); + Eina_Rect ipos, view; + Eina_Position2D vpos; + + if (!pd->smanager) return; + + ipos = efl_gfx_entity_geometry_get(item); + view = efl_ui_scrollable_viewport_geometry_get(pd->smanager); + vpos = efl_ui_scrollable_content_pos_get(pd->smanager); + + if (pd->dir == EFL_UI_DIR_HORIZONTAL) + { + ipos.y = view.y; + ipos.h = ipos.h; + + // FIXME: align case will not correctly show in the position because of + // bar size calculation. there are no certain way to know the scroll calcuation finished. + if (EINA_DBL_EQ(align, -1.0)) //Internal Prefix + { + ipos.x = ipos.x + vpos.x - view.x; + ipos.w = ipos.w; + } + else if ((align > 0.0 || EINA_DBL_EQ(align, 0.0)) && + (align < 1.0 || EINA_DBL_EQ(align, 1.0))) + { + ipos.x = ipos.x + vpos.x - view.x - (int)((view.w - ipos.w) * align); + ipos.w = view.w; + } + else ERR("align (%.2lf) is not proper value. it must be the value between [0.0 , 1.0]!", align); + + } + else //VERTICAL + { + ipos.x = view.x; + ipos.w = ipos.w; + + // FIXME: align case will not correctly show in the position because of + // bar size calculation. there are no certain way to know the scroll calcuation finished. + if (EINA_DBL_EQ(align, -1.0)) //Internal Prefix + { + ipos.y = ipos.y + vpos.y - view.y; + ipos.h = ipos.h; + } + else if ((align > 0.0 || EINA_DBL_EQ(align, 0.0)) && + (align < 1.0 || EINA_DBL_EQ(align, 1.0))) + { + ipos.y = ipos.y + vpos.y - view.y - (int)((view.h - ipos.h) * align); + ipos.h = view.h; + } + else ERR("align (%.2lf) is not proper value. it must be the value between [0.0 , 1.0]!", align); + } + + efl_ui_scrollable_scroll(pd->smanager, ipos, anim); +} + +static void +_efl_ui_grid_bar_read_and_update(Eo *obj) +{ + EFL_UI_GRID_DATA_GET_OR_RETURN(obj, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + double vx = 0.0, vy = 0.0; + + edje_object_part_drag_value_get + (wd->resize_obj, "efl.dragable.vbar", NULL, &vy); + + edje_object_part_drag_value_get + (wd->resize_obj, "efl.dragable.hbar", &vx, NULL); + + efl_ui_scrollbar_bar_position_set(pd->smanager, vx, vy); +} + +static void +_efl_ui_grid_reload_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Eo *list = data; + EFL_UI_GRID_DATA_GET_OR_RETURN(list, pd); + + efl_ui_scrollbar_bar_visibility_update(pd->smanager); +} + +static void +_efl_ui_grid_vbar_drag_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + _efl_ui_grid_bar_read_and_update(data); + + Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_VERTICAL; + efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_DRAG, &type); +} + +static void +_efl_ui_grid_vbar_press_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_VERTICAL; + efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_PRESS, &type); +} + +static void +_efl_ui_grid_vbar_unpress_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_VERTICAL; + efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_UNPRESS, &type); +} + +static void +_efl_ui_grid_edje_drag_start_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Eo *list = data; + EFL_UI_GRID_DATA_GET_OR_RETURN(list, pd); + + _efl_ui_grid_bar_read_and_update(list); + + pd->freeze_want = efl_ui_scrollable_scroll_freeze_get(pd->smanager); + efl_ui_scrollable_scroll_freeze_set(pd->smanager, EINA_TRUE); + efl_event_callback_call(list, EFL_UI_EVENT_SCROLL_DRAG_START, NULL); +} + +static void +_efl_ui_grid_edje_drag_stop_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Eo *list = data; + EFL_UI_GRID_DATA_GET_OR_RETURN(list, pd); + + _efl_ui_grid_bar_read_and_update(list); + + efl_ui_scrollable_scroll_freeze_set(pd->smanager, pd->freeze_want); + efl_event_callback_call(list, EFL_UI_EVENT_SCROLL_DRAG_STOP, NULL); +} + +static void +_efl_ui_grid_edje_drag_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + _efl_ui_grid_bar_read_and_update(data); +} + +static void +_efl_ui_grid_hbar_drag_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + _efl_ui_grid_bar_read_and_update(data); + + Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL; + efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_DRAG, &type); +} + +static void +_efl_ui_grid_hbar_press_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL; + efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_PRESS, &type); +} + +static void +_efl_ui_grid_hbar_unpress_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL; + efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_UNPRESS, &type); +} + +static void +_efl_ui_grid_bar_size_changed_cb(void *data, const Efl_Event *event EINA_UNUSED) +{ + Eo *obj = data; + EFL_UI_GRID_DATA_GET_OR_RETURN(obj, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + double width = 0.0, height = 0.0; + + edje_object_calc_force(wd->resize_obj); + efl_ui_scrollbar_bar_size_get(pd->smanager, &width, &height); + edje_object_part_drag_size_set(wd->resize_obj, "efl.dragable.hbar", width, 1.0); + edje_object_part_drag_size_set(wd->resize_obj, "efl.dragable.vbar", 1.0, height); +} + +static void +_efl_ui_grid_bar_pos_changed_cb(void *data, const Efl_Event *event EINA_UNUSED) +{ + Eo *obj = data; + EFL_UI_GRID_DATA_GET_OR_RETURN(obj, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + double posx = 0.0, posy = 0.0; + + efl_ui_scrollbar_bar_position_get(pd->smanager, &posx, &posy); + edje_object_part_drag_value_set(wd->resize_obj, "efl.dragable.hbar", posx, 0.0); + edje_object_part_drag_value_set(wd->resize_obj, "efl.dragable.vbar", 0.0, posy); +} + +static void +_efl_ui_grid_bar_show_cb(void *data, const Efl_Event *event) +{ + Eo *obj = data; + EFL_UI_GRID_DATA_GET_OR_RETURN(obj, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + Efl_Ui_Scrollbar_Direction type = *(Efl_Ui_Scrollbar_Direction *)(event->info); + + if (type == EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL) + edje_object_signal_emit(wd->resize_obj, "efl,action,show,hbar", "efl"); + else if (type == EFL_UI_SCROLLBAR_DIRECTION_VERTICAL) + edje_object_signal_emit(wd->resize_obj, "efl,action,show,vbar", "efl"); +} + +static void +_efl_ui_grid_bar_hide_cb(void *data, const Efl_Event *event) +{ + Eo *obj = data; + EFL_UI_GRID_DATA_GET_OR_RETURN(obj, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + Efl_Ui_Scrollbar_Direction type = *(Efl_Ui_Scrollbar_Direction *)(event->info); + + if (type == EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL) + edje_object_signal_emit(wd->resize_obj, "efl,action,hide,hbar", "efl"); + else if (type == EFL_UI_SCROLLBAR_DIRECTION_VERTICAL) + edje_object_signal_emit(wd->resize_obj, "efl,action,hide,vbar", "efl"); +} + +static void +_scroll_edje_object_attach(Eo *obj) +{ + EFL_UI_GRID_DATA_GET_OR_RETURN(obj, pd); + + efl_layout_signal_callback_add(obj, "reload", "efl", + _efl_ui_grid_reload_cb, obj); + efl_layout_signal_callback_add(obj, "drag", "efl.dragable.vbar", + _efl_ui_grid_vbar_drag_cb, obj); + efl_layout_signal_callback_add(obj, "drag,set", "efl.dragable.vbar", + _efl_ui_grid_edje_drag_cb, obj); + efl_layout_signal_callback_add(obj, "drag,start", "efl.dragable.vbar", + _efl_ui_grid_edje_drag_start_cb, obj); + efl_layout_signal_callback_add(obj, "drag,stop", "efl.dragable.vbar", + _efl_ui_grid_edje_drag_stop_cb, obj); + efl_layout_signal_callback_add(obj, "drag,step", "efl.dragable.vbar", + _efl_ui_grid_edje_drag_cb, obj); + efl_layout_signal_callback_add(obj, "drag,page", "efl.dragable.vbar", + _efl_ui_grid_edje_drag_cb, obj); + efl_layout_signal_callback_add(obj, "efl,vbar,press", "efl", + _efl_ui_grid_vbar_press_cb, obj); + efl_layout_signal_callback_add(obj, "efl,vbar,unpress", "efl", + _efl_ui_grid_vbar_unpress_cb, obj); + + efl_layout_signal_callback_add(obj, "drag", "efl.dragable.hbar", + _efl_ui_grid_hbar_drag_cb, obj); + efl_layout_signal_callback_add(obj, "drag,set", "efl.dragable.hbar", + _efl_ui_grid_edje_drag_cb, obj); + efl_layout_signal_callback_add(obj, "drag,start", "efl.dragable.hbar", + _efl_ui_grid_edje_drag_start_cb, obj); + efl_layout_signal_callback_add(obj, "drag,stop", "efl.dragable.hbar", + _efl_ui_grid_edje_drag_stop_cb, obj); + efl_layout_signal_callback_add(obj, "drag,step", "efl.dragable.hbar", + _efl_ui_grid_edje_drag_cb, obj); + efl_layout_signal_callback_add(obj, "drag,page", "efl.dragable.hbar", + _efl_ui_grid_edje_drag_cb, obj); + efl_layout_signal_callback_add(obj, "efl,hbar,press", "efl", + _efl_ui_grid_hbar_press_cb, obj); + efl_layout_signal_callback_add(obj, "efl,hbar,unpress", "efl", + _efl_ui_grid_hbar_unpress_cb, obj); +} + +static void +_scroll_edje_object_detach(Eo *obj) +{ + EFL_UI_GRID_DATA_GET_OR_RETURN(obj, pd); + + efl_layout_signal_callback_del(obj, "reload", "efl", + _efl_ui_grid_reload_cb, obj); + efl_layout_signal_callback_del(obj, "drag", "efl.dragable.vbar", + _efl_ui_grid_vbar_drag_cb, obj); + efl_layout_signal_callback_del(obj, "drag,set", "efl.dragable.vbar", + _efl_ui_grid_edje_drag_cb, obj); + efl_layout_signal_callback_del(obj, "drag,start", "efl.dragable.vbar", + _efl_ui_grid_edje_drag_start_cb, obj); + efl_layout_signal_callback_del(obj, "drag,stop", "efl.dragable.vbar", + _efl_ui_grid_edje_drag_stop_cb, obj); + efl_layout_signal_callback_del(obj, "drag,step", "efl.dragable.vbar", + _efl_ui_grid_edje_drag_cb, obj); + efl_layout_signal_callback_del(obj, "drag,page", "efl.dragable.vbar", + _efl_ui_grid_edje_drag_cb, obj); + efl_layout_signal_callback_del(obj, "efl,vbar,press", "efl", + _efl_ui_grid_vbar_press_cb, obj); + efl_layout_signal_callback_del(obj, "efl,vbar,unpress", "efl", + _efl_ui_grid_vbar_unpress_cb, obj); + + efl_layout_signal_callback_del(obj, "drag", "efl.dragable.hbar", + _efl_ui_grid_hbar_drag_cb, obj); + efl_layout_signal_callback_del(obj, "drag,set", "efl.dragable.hbar", + _efl_ui_grid_edje_drag_cb, obj); + efl_layout_signal_callback_del(obj, "drag,start", "efl.dragable.hbar", + _efl_ui_grid_edje_drag_start_cb, obj); + efl_layout_signal_callback_del(obj, "drag,stop", "efl.dragable.hbar", + _efl_ui_grid_edje_drag_stop_cb, obj); + efl_layout_signal_callback_del(obj, "drag,step", "efl.dragable.hbar", + _efl_ui_grid_edje_drag_cb, obj); + efl_layout_signal_callback_del(obj, "drag,page", "efl.dragable.hbar", + _efl_ui_grid_edje_drag_cb, obj); + efl_layout_signal_callback_del(obj, "efl,hbar,press", "efl", + _efl_ui_grid_hbar_press_cb, obj); + efl_layout_signal_callback_del(obj, "efl,hbar,unpress", "efl", + _efl_ui_grid_hbar_unpress_cb, obj); +} + +static void +_efl_ui_grid_content_moved_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + Eo *obj = data; + EFL_UI_GRID_DATA_GET_OR_RETURN(obj, pd); + if (!pd->smanager) return; + + efl_canvas_group_change(pd->obj); +} + +static void +_efl_ui_grid_pan_resized_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + Eo *obj = data; + EFL_UI_GRID_DATA_GET_OR_RETURN(obj, pd); + if (!pd->smanager) return; + + //reset linemax for recalculate layout. + pd->linemax = 0; + + _need_update(pd); + elm_layout_sizing_eval(obj); + + pd->pan_resized = EINA_TRUE; +} + +static void +_efl_ui_grid_resized_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + elm_layout_sizing_eval(data); +} + +static void +_efl_ui_grid_size_hint_changed_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + elm_layout_sizing_eval(data); +} + +EOLIAN static Eo * +_efl_ui_grid_efl_object_constructor(Eo *obj, Efl_Ui_Grid_Data *pd EINA_UNUSED) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + + return obj; +} + +EOLIAN static Eo * +_efl_ui_grid_efl_object_finalize(Eo *obj, + Efl_Ui_Grid_Data *pd) +{ + pd->obj = obj = efl_finalize(efl_super(obj, MY_CLASS)); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL); + + efl_ui_layout_theme_set(obj, "grid", "base", efl_ui_widget_style_get(obj)); + + pd->smanager = efl_add(EFL_UI_SCROLL_MANAGER_CLASS, obj); + efl_composite_attach(obj, pd->smanager); + efl_ui_mirrored_set(pd->smanager, efl_ui_mirrored_get(obj)); + + pd->pan = efl_add(EFL_UI_PAN_CLASS, obj); + + efl_ui_scroll_manager_pan_set(pd->smanager, pd->pan); + edje_object_part_swallow(wd->resize_obj, "efl.content", pd->pan); + + pd->select_mode = EFL_UI_SELECT_SINGLE; + + if ((pd->item.size.w == 0) && (pd->item.size.h == 0)) + { + pd->item.size.w = 1; + pd->item.size.h = 1; + } + + _scroll_edje_object_attach(obj); + + //FIXME: Workaround code! fake Content for pan resize. + // to remove this code, we need to customize pan class. + pd->content = efl_add(EFL_CANVAS_RECTANGLE_CLASS, evas_object_evas_get(obj)); + efl_gfx_color_set(pd->content, 0, 0, 0, 0); + efl_content_set(pd->pan, pd->content); + + efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SIZE_CHANGED, + _efl_ui_grid_bar_size_changed_cb, obj); + efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_POS_CHANGED, + _efl_ui_grid_bar_pos_changed_cb, obj); + efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SHOW, + _efl_ui_grid_bar_show_cb, obj); + efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_HIDE, + _efl_ui_grid_bar_hide_cb, obj); + efl_event_callback_add(obj, EFL_GFX_ENTITY_EVENT_RESIZE, + _efl_ui_grid_resized_cb, obj); + efl_event_callback_add(obj, EFL_GFX_ENTITY_EVENT_CHANGE_SIZE_HINTS, + _efl_ui_grid_size_hint_changed_cb, obj); + efl_event_callback_add(pd->pan, EFL_GFX_ENTITY_EVENT_RESIZE, + _efl_ui_grid_pan_resized_cb, obj); + efl_event_callback_add(pd->content, EFL_GFX_ENTITY_EVENT_MOVE, + _efl_ui_grid_content_moved_cb, obj); + + elm_layout_sizing_eval(obj); + + return obj; +} + + +EOLIAN static void +_efl_ui_grid_efl_object_invalidate(Eo *obj, Efl_Ui_Grid_Data *pd) +{ + _scroll_edje_object_detach(obj); + + efl_event_callback_del(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SIZE_CHANGED, + _efl_ui_grid_bar_size_changed_cb, obj); + efl_event_callback_del(obj, EFL_UI_SCROLLBAR_EVENT_BAR_POS_CHANGED, + _efl_ui_grid_bar_pos_changed_cb, obj); + efl_event_callback_del(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SHOW, + _efl_ui_grid_bar_show_cb, obj); + efl_event_callback_del(obj, EFL_UI_SCROLLBAR_EVENT_BAR_HIDE, + _efl_ui_grid_bar_hide_cb, obj); + efl_event_callback_del(obj, EFL_GFX_ENTITY_EVENT_RESIZE, + _efl_ui_grid_resized_cb, obj); + efl_event_callback_del(obj, EFL_GFX_ENTITY_EVENT_CHANGE_SIZE_HINTS, + _efl_ui_grid_size_hint_changed_cb, obj); + efl_event_callback_del(pd->pan, EFL_GFX_ENTITY_EVENT_RESIZE, + _efl_ui_grid_pan_resized_cb, obj); + efl_event_callback_del(pd->content, EFL_GFX_ENTITY_EVENT_MOVE, + _efl_ui_grid_content_moved_cb, obj); + _grid_clear_internal(obj, pd); + + if (pd->smanager) efl_del(pd->smanager); + pd->smanager = NULL; + if (pd->content) efl_del(pd->content); + pd->content = NULL; + if (pd->pan) efl_del(pd->pan); + pd->pan = NULL; + + efl_invalidate(efl_super(obj, MY_CLASS)); +} + +EOLIAN static void +_efl_ui_grid_efl_object_destructor(Eo *obj, Efl_Ui_Grid_Data *pd EINA_UNUSED) +{ + efl_destructor(efl_super(obj, MY_CLASS)); +} + +EOLIAN static void +_efl_ui_grid_efl_canvas_group_group_calculate(Eo *obj, Efl_Ui_Grid_Data *pd) +{ + + Eina_Position2D pos = efl_ui_scrollable_content_pos_get(pd->smanager); + Eina_Rect geo = efl_ui_scrollable_viewport_geometry_get(pd->smanager); + + //ERR("pos[%d,%d], geo[%d,%d,%d,%d]", pos.x, pos.y, geo.x, geo.y, geo.w, geo.h); + + if (geo.w <= 1 || geo.h <= 1) return; + // Need to be implemented + if (pd->need_update) + { + _relayout(obj, pd, pos); + } + else + { + if (pd->pre_pos.x != pos.x || pd->pre_pos.y != pos.y) + { + _reposition(obj, pd, pos); + } + } + + pd->pre_pos = pos; + + if (pd->pan_resized) + { + pd->pan_resized = EINA_FALSE; + // FIXME: Below code is workaround size check + if ((geo.h > 1) && (pd->scroll.item)) + { + _item_scroll_internal(obj, pd->scroll.item, pd->scroll.align, pd->scroll.anim); + + pd->scroll.item = NULL; + pd->scroll.align = 0.0; + pd->scroll.anim = EINA_FALSE; + return; + } + } + + efl_canvas_group_calculate(efl_super(obj, MY_CLASS)); +} + +EOLIAN static void +_efl_ui_grid_elm_layout_sizing_eval(Eo *obj, Efl_Ui_Grid_Data *pd) +{ + Eina_Size2D min = {0, 0}, max = {0, 0}, size = {-1, -1}; + Eina_Rect view = {}; + Evas_Coord vmw = 0, vmh = 0; + double xw = 0.0, yw = 0.0; + + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + + min = efl_gfx_size_hint_combined_min_get(obj); + max = efl_gfx_size_hint_max_get(obj); + + if (pd->smanager) + view = efl_ui_scrollable_viewport_geometry_get(pd->smanager); + + if (xw > 0.0) + { + if ((min.w > 0) && (view.w < min.w)) + view.w = min.w; + else if ((max.w > 0) && (view.w > max.w)) + view.w = max.w; + } + else if (min.w > 0) + view.w = min.w; + + if (yw > 0.0) + { + if ((min.h > 0) && (view.h < min.h)) + view.h = min.h; + else if ((max.h > 0) && (view.h > max.h)) + view.h = max.h; + } + else if (min.h > 0) + view.h = min.h; + + edje_object_size_min_calc(wd->resize_obj, &vmw, &vmh); + + if (pd->match_content_w) size.w = vmw + min.w; + if (pd->match_content_h) size.h = vmh + min.h; + + max = efl_gfx_size_hint_max_get(obj); + if ((max.w > 0) && (size.w > max.w)) size.w = max.w; + if ((max.h > 0) && (size.h > max.h)) size.h = max.h; + pd->geo = view; + efl_gfx_size_hint_min_set(obj, size); + + _need_update(pd); + return; +} + +EOLIAN static int +_efl_ui_grid_efl_container_content_count(Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd) +{ + return eina_list_count(pd->items); +} + +static Eina_Bool +_grid_item_iterator_next(Item_Iterator *it, void **data) +{ + Efl_Ui_Grid_Item *item; + + if (!eina_iterator_next(it->real_iterator, (void **)&item)) + return EINA_FALSE; + + if (data) *data = item; + return EINA_TRUE; +} + +static Eo * +_grid_item_iterator_get_container(Item_Iterator *it) +{ + return it->object; +} + +static void +_grid_item_iterator_free(Item_Iterator *it) +{ + eina_iterator_free(it->real_iterator); + eina_list_free(it->list); + free(it); +} + +static Eina_Iterator * +_grid_item_iterator_new(Eo *obj, Eina_List *list) +{ + // NEED-TO-IMPLEMENTS + Item_Iterator *item; + + item = calloc(1, sizeof(*item)); + if (!item) return NULL; + + EINA_MAGIC_SET(&item->iterator, EINA_MAGIC_ITERATOR); + + item->list = eina_list_clone(list); + item->real_iterator = eina_list_iterator_new(item->list); + item->iterator.version = EINA_ITERATOR_VERSION; + item->iterator.next = FUNC_ITERATOR_NEXT(_grid_item_iterator_next); + item->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_grid_item_iterator_get_container); + item->iterator.free = FUNC_ITERATOR_FREE(_grid_item_iterator_free); + item->object = obj; + + return &item->iterator; +} + +EOLIAN static Eina_Iterator * +_efl_ui_grid_efl_container_content_iterate(Eo *obj, Efl_Ui_Grid_Data *pd) +{ + return _grid_item_iterator_new(obj, pd->items); +} + +EOLIAN static void +_efl_ui_grid_efl_ui_direction_direction_set(Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd, Efl_Ui_Dir dir) +{ + //FIXME: Currently only support horizontal and vertical mode. + switch (dir) + { + case EFL_UI_DIR_RTL: + // FIXME: Should be inverted! + case EFL_UI_DIR_HORIZONTAL: + case EFL_UI_DIR_LTR: + pd->dir = EFL_UI_DIR_HORIZONTAL; + break; + + case EFL_UI_DIR_UP: + // FIXME: Should be inverted! + case EFL_UI_DIR_DOWN: + case EFL_UI_DIR_VERTICAL: + case EFL_UI_DIR_DEFAULT: + default: + pd->dir = EFL_UI_DIR_VERTICAL; + break; + } + + pd->linemax = 0; + efl_pack_layout_request(obj); +} + +EOLIAN static Efl_Ui_Dir +_efl_ui_grid_efl_ui_direction_direction_get(const Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd) +{ + return pd->dir; +} + + +EOLIAN static Efl_Ui_Theme_Apply_Result +_efl_ui_grid_efl_ui_widget_theme_apply(Eo *obj, Efl_Ui_Grid_Data *pd) +{ + Efl_Ui_Theme_Apply_Result int_ret = EFL_UI_THEME_APPLY_RESULT_FAIL; + int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS)); + if (!int_ret) return EFL_UI_THEME_APPLY_RESULT_FAIL; + + efl_ui_mirrored_set(pd->smanager, efl_ui_mirrored_get(obj)); + + elm_layout_sizing_eval(obj); + + return int_ret; +} + +static void +_grid_item_pressed(void *data, const Efl_Event *event) +{ + Eo *obj = data; + Efl_Ui_Grid_Item *item = event->object; + efl_event_callback_call(obj, EFL_UI_EVENT_PRESSED, item); +} + +static void +_grid_item_unpressed(void *data, const Efl_Event *event) +{ + Eo *obj = data; + Efl_Ui_Grid_Item *item = event->object; + efl_event_callback_call(obj, EFL_UI_EVENT_UNPRESSED, item); +} + +static void +_grid_item_longpressed(void *data, const Efl_Event *event) +{ + Eo *obj = data; + Efl_Ui_Grid_Item *item = event->object; + efl_event_callback_call(obj, EFL_UI_EVENT_LONGPRESSED, item); +} + +static void +_grid_item_selected(void *data, const Efl_Event *event) +{ + Eo *obj = data; + Efl_Ui_Grid_Item *item = event->object; + Efl_Ui_Grid_Item *selected; + EFL_UI_GRID_DATA_GET_OR_RETURN(obj, pd); + + /* Single Select */ + if (pd->select_mode != EFL_UI_SELECT_MULTI) + { + EINA_LIST_FREE(pd->selected, selected) + { + if (selected != item) + efl_ui_item_selected_set(selected, EINA_FALSE); + } + } + pd->selected = eina_list_append(pd->selected, item); + pd->last_selected = item; + + efl_event_callback_call(obj, EFL_UI_EVENT_SELECTED, item); +} + +static void +_grid_item_unselected(void *data, const Efl_Event *event) +{ + Eo *obj = data; + Efl_Ui_Grid_Item *item = event->object; + EFL_UI_GRID_DATA_GET_OR_RETURN(obj, pd); + + pd->selected = eina_list_remove(pd->selected, item); + if (pd->last_selected == item) pd->last_selected = NULL; + + efl_event_callback_call(obj, EFL_UI_EVENT_UNSELECTED, item); +} + +static void +_grid_item_deleted(void *data, const Efl_Event *event) +{ + Eo *obj = data; + Efl_Ui_Grid_Item *it = event->object; + EFL_UI_GRID_DATA_GET(obj, pd); + _grid_item_unpack_internal(obj, pd, it); +} + +static Eina_Bool +_grid_item_process(Eo *obj, Efl_Ui_Grid_Data *pd, EINA_UNUSED Efl_Ui_Grid_Item *it) +{ + EFL_UI_GRID_ITEM_CHECK_OR_RETURN(it, EINA_FALSE); + + //FIXME: This is tricky workaround for set select mode and parent value. + EFL_UI_GRID_ITEM_DATA_GET(it, gd); + EFL_UI_ITEM_DATA_GET(it, id); + id->select_mode = &(pd->select_mode); + id->parent = obj; + gd->parent = obj; + efl_canvas_group_member_add(pd->pan, it); + efl_ui_mirrored_set(it, efl_ui_mirrored_get(obj)); + + efl_event_callback_add(it, EFL_UI_EVENT_PRESSED, _grid_item_pressed, obj); + efl_event_callback_add(it, EFL_UI_EVENT_UNPRESSED, _grid_item_unpressed, obj); + efl_event_callback_add(it, EFL_UI_EVENT_LONGPRESSED, _grid_item_longpressed, obj); + efl_event_callback_add(it, EFL_UI_EVENT_SELECTED, _grid_item_selected, obj); + efl_event_callback_add(it, EFL_UI_EVENT_UNSELECTED, _grid_item_unselected, obj); + efl_event_callback_add(it, EFL_EVENT_DEL, _grid_item_deleted, obj); + + return EINA_TRUE; +} + +static void +_grid_item_unpack_internal(Eo *obj, Efl_Ui_Grid_Data *pd, Efl_Ui_Grid_Item *it) +{ + EFL_UI_GRID_ITEM_CHECK_OR_RETURN(it); + EFL_UI_GRID_ITEM_DATA_GET(it, ld); + EFL_UI_ITEM_DATA_GET(it, id); + id->select_mode = NULL; + id->parent = NULL; + ld->parent = NULL; + + pd->items = eina_list_remove(pd->items, it); + if (efl_ui_item_selected_get(it)) + { + pd->selected = eina_list_remove(pd->selected, it); + } + + efl_event_callback_del(it, EFL_UI_EVENT_PRESSED, _grid_item_pressed, obj); + efl_event_callback_del(it, EFL_UI_EVENT_UNPRESSED, _grid_item_unpressed, obj); + efl_event_callback_del(it, EFL_UI_EVENT_LONGPRESSED, _grid_item_longpressed, obj); + efl_event_callback_del(it, EFL_UI_EVENT_SELECTED, _grid_item_selected, obj); + efl_event_callback_del(it, EFL_UI_EVENT_UNSELECTED, _grid_item_unselected, obj); + efl_event_callback_del(it, EFL_EVENT_DEL, _grid_item_deleted, obj); +} + + +static void +_grid_clear_internal(Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd) +{ + Efl_Ui_Grid_Item *it = NULL; + Eina_List *l, *ll; + EINA_LIST_FOREACH_SAFE(pd->items, l, ll, it) + { + efl_del(it); + } + eina_list_free(pd->selected); + pd->items = NULL; + pd->selected = NULL; +} + +/* Pack APIs */ +EOLIAN static Eina_Bool +_efl_ui_grid_efl_pack_pack_clear(Eo *obj, Efl_Ui_Grid_Data *pd) +{ + _grid_clear_internal(obj, pd); + + elm_layout_sizing_eval(obj); + return EINA_TRUE; +} + +EOLIAN static Eina_Bool +_efl_ui_grid_efl_pack_unpack_all(Eo *obj, Efl_Ui_Grid_Data *pd) +{ + + Efl_Ui_Grid_Item *it = NULL; + Eina_List *l, *ll; + EINA_LIST_FOREACH_SAFE(pd->items, l, ll, it) + { + _grid_item_unpack_internal(obj, pd, it); + } + eina_list_free(pd->selected); + pd->items = NULL; + pd->selected = NULL; + + elm_layout_sizing_eval(obj); + return EINA_TRUE; +} + +EOLIAN static Eina_Bool +_efl_ui_grid_efl_pack_unpack(Eo *obj, Efl_Ui_Grid_Data *pd, Efl_Gfx_Entity *subobj) +{ + Efl_Ui_Grid_Item *item = (Efl_Ui_Grid_Item *)subobj; + + _grid_item_unpack_internal(obj, pd, item); + + elm_layout_sizing_eval(obj); + return EINA_TRUE; +} + +EOLIAN static Eina_Bool +_efl_ui_grid_efl_pack_pack(Eo *obj, Efl_Ui_Grid_Data *pd EINA_UNUSED, Efl_Gfx_Entity *subobj) +{ + return efl_pack_end(obj, subobj); +} + +EOLIAN static Eina_Bool +_efl_ui_grid_efl_pack_linear_pack_end(Eo *obj, Efl_Ui_Grid_Data *pd, Efl_Gfx_Entity *subobj) +{ + if (!_grid_item_process(obj, pd, subobj)) return EINA_FALSE; + EFL_UI_GRID_ITEM_DATA_GET(subobj, pid); + pd->items = eina_list_append(pd->items, subobj); + + pid->update_me = EINA_TRUE; + + efl_canvas_group_change(obj); + return EINA_TRUE; +} + +EOLIAN static Eina_Bool +_efl_ui_grid_efl_pack_linear_pack_begin(Eo *obj, Efl_Ui_Grid_Data *pd, Efl_Gfx_Entity *subobj) +{ + if (!_grid_item_process(obj, pd, subobj)) return EINA_FALSE; + EFL_UI_GRID_ITEM_DATA_GET(subobj, pid); + pd->items = eina_list_prepend(pd->items, subobj); + // Defered item's placing in group calculation + pid->update_me = EINA_TRUE; + _need_update(pd); + return EINA_TRUE; +} + +EOLIAN static Eina_Bool +_efl_ui_grid_efl_pack_linear_pack_before(Eo *obj, + Efl_Ui_Grid_Data *pd, + Efl_Gfx_Entity *subobj, + const Efl_Gfx_Entity *existing) +{ + if (!_grid_item_process(obj, pd, subobj)) return EINA_FALSE; + EFL_UI_GRID_ITEM_CHECK_OR_RETURN(existing, EINA_FALSE); + EFL_UI_GRID_ITEM_DATA_GET(subobj, pid); + + pd->items = eina_list_prepend_relative(pd->items, subobj, existing); + // Defered item's placing in group calculation + pid->update_begin = EINA_TRUE; + _need_update(pd); + return EINA_TRUE; +} + +EOLIAN static Eina_Bool +_efl_ui_grid_efl_pack_linear_pack_after(Eo *obj, + Efl_Ui_Grid_Data *pd, + Efl_Gfx_Entity *subobj, + const Efl_Gfx_Entity *existing) +{ + if (!_grid_item_process(obj, pd, subobj)) return EINA_FALSE; + EFL_UI_GRID_ITEM_CHECK_OR_RETURN(existing, EINA_FALSE); + EFL_UI_GRID_ITEM_DATA_GET(subobj, pid); + + pd->items = eina_list_append_relative(pd->items, subobj, existing); + // Defered item's placing in group calculation + pid->update_begin = EINA_TRUE; + _need_update(pd); + return EINA_TRUE; +} + +EOLIAN static Eina_Bool +_efl_ui_grid_efl_pack_linear_pack_at(Eo *obj, + Efl_Ui_Grid_Data *pd, + Efl_Gfx_Entity *subobj, + int index) +{ + if (!_grid_item_process(obj, pd, subobj)) return EINA_FALSE; + Efl_Ui_Grid_Item *existing = eina_list_nth(pd->items, index); + EFL_UI_GRID_ITEM_DATA_GET(subobj, pid); + + pd->items = eina_list_prepend_relative(pd->items, subobj, existing); + // Defered item's placing in group calculation + pid->update_begin = EINA_TRUE; + _need_update(pd); + return EINA_TRUE; +} + +EOLIAN static Efl_Gfx_Entity * +_efl_ui_grid_efl_pack_linear_pack_content_get(Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd, int index) +{ + return eina_list_nth(pd->items, index); +} + +EOLIAN static Efl_Gfx_Entity * +_efl_ui_grid_efl_pack_linear_pack_unpack_at(Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd, int index) +{ + Efl_Gfx_Entity *target = eina_list_nth(pd->items, index); + pd->items = eina_list_remove(pd->items, target); + /* + if (after) + { + } + else + */ + _need_update(pd); + return target; +} + +EOLIAN static int +_efl_ui_grid_efl_pack_linear_pack_index_get(Eo *obj EINA_UNUSED, + Efl_Ui_Grid_Data *pd, + const Efl_Gfx_Entity *subobj) +{ + return eina_list_data_idx(pd->items, (void *)subobj); +} + +EOLIAN static void +_efl_ui_grid_efl_pack_layout_layout_update(Eo *obj, Efl_Ui_Grid_Data *pd) +{ + _need_update(pd); + elm_layout_sizing_eval(obj); + + efl_event_callback_legacy_call(obj, EFL_PACK_EVENT_LAYOUT_UPDATED, NULL); +} + +EOLIAN static void +_efl_ui_grid_efl_pack_layout_layout_request(Eo *obj, Efl_Ui_Grid_Data *pd) +{ + _need_update(pd); + elm_layout_sizing_eval(obj); +} + +EOLIAN static void +_efl_ui_grid_efl_pack_pack_padding_set(Eo *obj EINA_UNUSED, + Efl_Ui_Grid_Data *pd, + double h, + double v, + Eina_Bool scalable) +{ + pd->item.pad.w = (int )h; + pd->item.pad.h = (int) v; + + pd->pad_scalable = !!scalable; + + //reset linemax for recalculate layout + pd->linemax = 0; + _need_update(pd); +} + +EOLIAN static void +_efl_ui_grid_efl_pack_pack_padding_get(const Eo *obj EINA_UNUSED, + Efl_Ui_Grid_Data *pd, + double *h, + double *v, + Eina_Bool *scalable) +{ + //?? + *h = (double) pd->item.pad.w; + *v = (double) pd->item.pad.h; + *scalable = !!pd->pad_scalable; +} + +EOLIAN static void +_efl_ui_grid_efl_pack_pack_align_set(Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd, double h, double v) +{ + pd->item.align.w = h; + pd->item.align.h = v; + _need_update(pd); +} + +EOLIAN static void +_efl_ui_grid_efl_pack_pack_align_get(const Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd, double *h, double *v) +{ + *h = pd->item.align.w; + *v = pd->item.align.h; +} + +EOLIAN static void +_efl_ui_grid_efl_ui_scrollable_interactive_match_content_set(Eo *obj EINA_UNUSED, + Efl_Ui_Grid_Data *pd, + Eina_Bool match_content_w, + Eina_Bool match_content_h) +{ + pd->match_content_w = !!match_content_w; + pd->match_content_h = !!match_content_h; + + efl_ui_scrollable_match_content_set(pd->smanager, match_content_w, match_content_h); + + elm_layout_sizing_eval(obj); +} + +EOLIAN static void +_efl_ui_grid_efl_ui_multi_selectable_select_mode_set(Eo *obj EINA_UNUSED, + Efl_Ui_Grid_Data *pd, + Efl_Ui_Select_Mode mode) +{ + Efl_Ui_Grid_Item *selected; + + if ((pd->select_mode == EFL_UI_SELECT_MULTI && + mode != EFL_UI_SELECT_MULTI) || + mode == EFL_UI_SELECT_NONE) + { + Eina_List *clone = eina_list_clone(pd->selected); + EINA_LIST_FREE(clone, selected) + efl_ui_item_selected_set(selected, EINA_FALSE); + } + + pd->select_mode = mode; +} + +EOLIAN static Efl_Ui_Select_Mode +_efl_ui_grid_efl_ui_multi_selectable_select_mode_get(const Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd) +{ + return pd->select_mode; +} + +/* List APIs */ +EOLIAN static void +_efl_ui_grid_item_scroll(Eo *obj, + Efl_Ui_Grid_Data *pd, + Efl_Ui_Grid_Item *item, + Eina_Bool animation) +{ + // Need to be implemented here. + if (pd->pan_resized) + { + _item_scroll_internal(obj, item, -1.0, animation); + } + else + { + pd->scroll.item = item; + pd->scroll.align = -1.0; + pd->scroll.anim = animation; + } +} + +EOLIAN static void +_efl_ui_grid_item_scroll_align(Eo *obj, + Efl_Ui_Grid_Data *pd, + Efl_Ui_Grid_Item *item, + double align, + Eina_Bool animation) +{ + // Need to be implemented here. + if (pd->pan_resized) + { + _item_scroll_internal(obj, item, align, animation); + } + else + { + pd->scroll.item = item; + pd->scroll.align = align; + pd->scroll.anim = animation; + } +} + +EOLIAN static Efl_Ui_Grid_Item * +_efl_ui_grid_last_selected_item_get(const Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd) +{ + return pd->last_selected; +} + +EOLIAN static Eina_Iterator * +_efl_ui_grid_selected_items_get(Eo *obj, Efl_Ui_Grid_Data *pd) +{ + return _grid_item_iterator_new(obj, pd->selected); +} + +EOLIAN static void +_efl_ui_grid_item_size_set(Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd, Eina_Size2D size) +{ + pd->item.size = size; + //reset linemax for recalculate layout. + pd->linemax = 0; + + _need_update(pd); +} + +EOLIAN static Eina_Size2D +_efl_ui_grid_item_size_get(const Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd) +{ + return pd->item.size; +} + +/* Internal EO APIs and hidden overrides */ +#define EFL_UI_GRID_EXTRA_OPS \ + ELM_LAYOUT_SIZING_EVAL_OPS(efl_ui_grid) + +#include "efl_ui_grid.eo.c" diff --git a/src/lib/elementary/efl_ui_grid.eo b/src/lib/elementary/efl_ui_grid.eo new file mode 100644 index 0000000000..7f92c0dc9f --- /dev/null +++ b/src/lib/elementary/efl_ui_grid.eo @@ -0,0 +1,96 @@ +import efl_ui_grid_item; + +class Efl.Ui.Grid (Efl.Ui.Layout, + Efl.Ui.Scrollable_Interactive, + Efl.Ui.Scrollbar, + Efl.Pack_Linear, Efl.Pack_Layout, + Efl.Ui.Direction, + Efl.Ui.Clickable, + Efl.Ui.Selectable, + Efl.Ui.Multi_Selectable) +{ + [[Simple grid widget with Pack interface.]] + methods { + @property item_size { + [[Property data of item size.]] + set {} + get {} + values { + size: Eina.Size2D; [[last selected item of grid.]] + } + } + item_scroll { + [[scroll move the item to show in the viewport.]] + params { + @in item: Efl.Ui.Grid_Item; [[Target item.]] + @in animation: bool; [[Boolean value for animation of scroll move.]] + } + } + item_scroll_align { + [[scroll move the item to show at the align position of the viewport.]] + params { + @in item: Efl.Ui.Grid_Item; [[Target item.]] + @in align: double; [[align value in Viewport.]] + @in animation: bool; [[Boolean value for animation of scroll move.]] + } + } + @property last_selected_item { + [[Property data of last selected item.]] + get {} + values { + item: Efl.Ui.Grid_Item; [[last selected item of grid.]] + } + } + selected_items_get { + [[Get the selected items iterator. The iterator sequence will be decided by selection.]] + return: iterator @owned @warn_unused; [[Iterator covered by selected items list. + user have to free the iterator after used.]] + } + } + implements { + //Efl.Object + Efl.Object.constructor; + Efl.Object.finalize; + Efl.Object.destructor; + Efl.Object.invalidate; + + //Efl.Canvas + Efl.Canvas.Group.group_calculate; + //Efl.Container + Efl.Container.content_iterate; + Efl.Container.content_count; + + Efl.Ui.Direction.direction { get; set; } + + //Efl.Ui.Widget + Efl.Ui.Widget.theme_apply; + + //Efl.Ui.Focus + //Efl.Ui.Focus.Object.on_focus_update; + + //Efl.Pack + Efl.Pack.pack_clear; + Efl.Pack.unpack_all; + Efl.Pack.unpack; + Efl.Pack.pack; + Efl.Pack_Linear.pack_end; + + Efl.Pack_Linear.pack_begin; + Efl.Pack_Linear.pack_before; + Efl.Pack_Linear.pack_after; + Efl.Pack_Linear.pack_at; + Efl.Pack_Linear.pack_unpack_at; + Efl.Pack_Linear.pack_index_get; + Efl.Pack_Linear.pack_content_get; + Efl.Pack_Layout.layout_update; + Efl.Pack_Layout.layout_request; + Efl.Pack.pack_padding { get; set; } + Efl.Pack.pack_align { get; set; } + + //Efl.Ui.Scrollable + Efl.Ui.Scrollable_Interactive.match_content { set; } + + //Efl.Ui.Multi_Selectable + Efl.Ui.Multi_Selectable.select_mode {get; set;} + } +} diff --git a/src/lib/elementary/efl_ui_grid_default_item.c b/src/lib/elementary/efl_ui_grid_default_item.c new file mode 100644 index 0000000000..ffc5e674a0 --- /dev/null +++ b/src/lib/elementary/efl_ui_grid_default_item.c @@ -0,0 +1,112 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define EFL_UI_GRID_DEFAULT_ITEM_PROTECTED +#define EFL_PART_PROTECTED + +#include + +#include "elm_priv.h" +#include "efl_ui_grid_default_item_part_icon.eo.h" +#include "efl_ui_grid_default_item_part_end.eo.h" +#include "elm_part_helper.h" + +#define MY_CLASS EFL_UI_GRID_DEFAULT_ITEM_CLASS +#define MY_CLASS_PFX efl_ui_grid_default_item + +#define MY_CLASS_NAME "Efl.Ui.Grid_Default_Item" + +EOLIAN static Efl_Object * +_efl_ui_grid_default_item_efl_object_finalize(Eo *obj, void *pd EINA_UNUSED) +{ + Eo *eo; + eo = efl_finalize(efl_super(obj, MY_CLASS)); + ELM_WIDGET_DATA_GET_OR_RETURN(eo, wd, eo); + Efl_Ui_Theme_Apply_Result theme_apply = efl_ui_layout_theme_set(obj, "grid_item", NULL, NULL); + + if (theme_apply == EFL_UI_THEME_APPLY_RESULT_FAIL) + CRI("Default Item(%p) failed to set theme [efl/grid_item]!", eo); + return eo; +} + +EOLIAN static void +_efl_ui_grid_default_item_efl_object_destructor(Eo *obj, void *pd EINA_UNUSED) +{ + efl_destructor(efl_super(obj, MY_CLASS)); +} + +/* Efl.Part */ + +ELM_PART_TEXT_DEFAULT_GET(efl_ui_grid_default_item, "efl.text") +ELM_PART_TEXT_DEFAULT_IMPLEMENT(efl_ui_grid_default_item, void) +ELM_PART_MARKUP_DEFAULT_IMPLEMENT(efl_ui_grid_default_item, void) +ELM_PART_CONTENT_DEFAULT_GET(efl_ui_grid_default_item, "efl.icon") +ELM_PART_CONTENT_DEFAULT_IMPLEMENT(efl_ui_grid_default_item, void +) + +Eina_Bool +_efl_ui_grid_default_item_part_icon_efl_content_content_set(Eo *obj, void *pd EINA_UNUSED, Efl_Gfx_Entity *content) +{ + Elm_Part_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + return efl_content_set(efl_part(efl_super(wd->obj, MY_CLASS), wd->part), content); +} + +Efl_Gfx_Entity * +_efl_ui_grid_default_item_part_icon_efl_content_content_get(const Eo *obj, void *pd EINA_UNUSED) +{ + Elm_Part_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + return efl_content_get(efl_part(efl_super(wd->obj, MY_CLASS), wd->part)); +} + +Efl_Gfx_Entity * +_efl_ui_grid_default_item_part_icon_efl_content_content_unset(Eo *obj, void *pd EINA_UNUSED) +{ + Elm_Part_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + return efl_content_unset(efl_part(efl_super(wd->obj, MY_CLASS), wd->part)); +} +#include "efl_ui_grid_default_item_part_icon.eo.c" + +Eina_Bool +_efl_ui_grid_default_item_part_end_efl_content_content_set(Eo *obj, void *pd EINA_UNUSED, Efl_Gfx_Entity *content) +{ + Elm_Part_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + return efl_content_set(efl_part(efl_super(wd->obj, MY_CLASS), wd->part), content); +} + +Efl_Gfx_Entity * +_efl_ui_grid_default_item_part_end_efl_content_content_get(const Eo *obj, void *pd EINA_UNUSED) +{ + Elm_Part_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + return efl_content_get(efl_part(efl_super(wd->obj, MY_CLASS), wd->part)); +} + +Efl_Gfx_Entity * +_efl_ui_grid_default_item_part_end_efl_content_content_unset(Eo *obj, void *pd EINA_UNUSED) +{ + Elm_Part_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + return efl_content_unset(efl_part(efl_super(wd->obj, MY_CLASS), wd->part)); +} +#include "efl_ui_grid_default_item_part_end.eo.c" + +EOLIAN static Efl_Object * +_efl_ui_grid_default_item_efl_part_part_get(const Eo *obj, void *wd EINA_UNUSED, const char *part) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL); + if (eina_streq(part, "text")) + return ELM_PART_IMPLEMENT(EFL_UI_LAYOUT_PART_TEXT_CLASS, obj, "efl.text"); + else if (eina_streq(part, "icon")) + return ELM_PART_IMPLEMENT(EFL_UI_GRID_DEFAULT_ITEM_PART_ICON_CLASS, obj, "efl.icon"); + else if (eina_streq(part, "end")) + return ELM_PART_IMPLEMENT(EFL_UI_GRID_DEFAULT_ITEM_PART_END_CLASS, obj, "efl.end"); + + return efl_part_get(efl_super(obj, MY_CLASS), part); +} +/* Efl.Part end */ + +/* Internal EO APIs and hidden overrides */ +#define EFL_UI_GRID_DEFAULT_ITEM_EXTRA_OPS \ + ELM_PART_TEXT_DEFAULT_OPS(efl_ui_grid_default_item), \ + ELM_PART_CONTENT_DEFAULT_OPS(efl_ui_grid_default_item) + +#include "efl_ui_grid_default_item.eo.c" diff --git a/src/lib/elementary/efl_ui_grid_default_item.eo b/src/lib/elementary/efl_ui_grid_default_item.eo new file mode 100644 index 0000000000..425ed14582 --- /dev/null +++ b/src/lib/elementary/efl_ui_grid_default_item.eo @@ -0,0 +1,28 @@ + +class Efl.Ui.Grid_Default_Item (Efl.Ui.Grid_Item, + Efl.Text, + Efl.Text_Markup, + Efl.Ui.Translatable, + Efl.Content) +{ + [[Grid Default Item class. + This class need to be sub object of list widget. + text and contents can be appliable by efl_text, + efl_content or efl_part APIs.]] + data: null; + parts { + icon: Efl.Ui.Grid_Default_Item_Part_Icon; [[]] + end: Efl.Ui.Grid_Default_Item_Part_End; [[]] + } + implements { + //Efl.Object + Efl.Object.finalize; + Efl.Object.destructor; + Efl.Text.text { get; set; } + Efl.Text_Markup.markup { get; set; } + Efl.Ui.Translatable.translatable_text { get; set; } + Efl.Content.content { get; set; } + Efl.Content.content_unset; + Efl.Part.part_get; + } +} diff --git a/src/lib/elementary/efl_ui_grid_default_item_part_end.eo b/src/lib/elementary/efl_ui_grid_default_item_part_end.eo new file mode 100644 index 0000000000..486ccbd98f --- /dev/null +++ b/src/lib/elementary/efl_ui_grid_default_item_part_end.eo @@ -0,0 +1,9 @@ +class Efl.Ui.Grid_Default_Item_Part_End (Efl.Ui.Layout_Part, Efl.Content) +{ + [[Grid Default Item internal content of end part class]] + data: null; + implements { + Efl.Content.content { get; set; } + Efl.Content.content_unset; + } +} diff --git a/src/lib/elementary/efl_ui_grid_default_item_part_icon.eo b/src/lib/elementary/efl_ui_grid_default_item_part_icon.eo new file mode 100644 index 0000000000..75436f6f7c --- /dev/null +++ b/src/lib/elementary/efl_ui_grid_default_item_part_icon.eo @@ -0,0 +1,9 @@ +class Efl.Ui.Grid_Default_Item_Part_Icon (Efl.Ui.Layout_Part, Efl.Content) +{ + [[Grid Default Item internal content of icon part class]] + data: null; + implements { + Efl.Content.content { get; set; } + Efl.Content.content_unset; + } +} diff --git a/src/lib/elementary/efl_ui_grid_item.c b/src/lib/elementary/efl_ui_grid_item.c new file mode 100644 index 0000000000..29daea7896 --- /dev/null +++ b/src/lib/elementary/efl_ui_grid_item.c @@ -0,0 +1,83 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define EFL_ACCESS_PROTECTED +#define EFL_UI_WIDGET_PART_BG_PROTECTED + +#include + +#include "elm_priv.h" +#include "efl_ui_grid_item_private.h" + +#define MY_CLASS EFL_UI_GRID_ITEM_CLASS +#define MY_CLASS_PFX efl_ui_grid_item + +#define MY_CLASS_NAME "Efl.Ui.Grid_Item" + +static void +_sizing_eval(Evas_Object *obj, Efl_Ui_Grid_Item_Data *pd) +{ + Evas_Coord minh = -1, minw = -1; + Evas_Coord rest_w = 0, rest_h = 0; + ELM_WIDGET_DATA_GET_OR_RETURN(pd->obj, wd); + + edje_object_size_min_restricted_calc(wd->resize_obj, &minw, &minh, + rest_w, rest_h); + evas_object_size_hint_min_set(obj, minw, minh); + + pd->needs_size_calc = EINA_FALSE; +} + +static void +_efl_ui_grid_item_elm_layout_sizing_eval(Eo *obj, Efl_Ui_Grid_Item_Data *pd) +{ + if (pd->needs_size_calc) return; + pd->needs_size_calc = EINA_TRUE; + + efl_canvas_group_change(obj); +} + +EOLIAN static void +_efl_ui_grid_item_efl_canvas_group_group_calculate(Eo *obj, Efl_Ui_Grid_Item_Data *pd) +{ + if (pd->needs_size_calc) + { + _sizing_eval(obj, pd); + pd->needs_size_calc = EINA_FALSE; + } +} + +EOLIAN static Eo * +_efl_ui_grid_item_efl_object_constructor(Eo *obj, Efl_Ui_Grid_Item_Data *pd) +{ + pd->obj = obj; + obj = efl_constructor(efl_super(obj, MY_CLASS)); + + return obj; +} + +EOLIAN static Efl_Object * +_efl_ui_grid_item_efl_object_finalize(Eo *obj, Efl_Ui_Grid_Item_Data *pd EINA_UNUSED) +{ + Eo *eo; + eo = efl_finalize(efl_super(obj, MY_CLASS)); + ELM_WIDGET_DATA_GET_OR_RETURN(eo, wd, eo); + + return eo; +} + +EOLIAN static void +_efl_ui_grid_item_efl_object_destructor(Eo *obj, Efl_Ui_Grid_Item_Data *pd EINA_UNUSED) +{ + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + efl_destructor(efl_super(obj, MY_CLASS)); +} + +/* Internal EO APIs and hidden overrides */ + +#define EFL_UI_GRID_ITEM_EXTRA_OPS \ + ELM_LAYOUT_SIZING_EVAL_OPS(efl_ui_grid_item) + +#include "efl_ui_grid_item.eo.c" diff --git a/src/lib/elementary/efl_ui_grid_item.eo b/src/lib/elementary/efl_ui_grid_item.eo new file mode 100644 index 0000000000..6c2eeeda01 --- /dev/null +++ b/src/lib/elementary/efl_ui_grid_item.eo @@ -0,0 +1,12 @@ + +abstract Efl.Ui.Grid_Item (Efl.Ui.Item) +{ + implements { + //Efl.Object + Efl.Object.constructor; + Efl.Object.finalize; + Efl.Object.destructor; + //Efl.Canvas + Efl.Canvas.Group.group_calculate; + } +} diff --git a/src/lib/elementary/efl_ui_grid_item_private.h b/src/lib/elementary/efl_ui_grid_item_private.h new file mode 100644 index 0000000000..cec53f91ce --- /dev/null +++ b/src/lib/elementary/efl_ui_grid_item_private.h @@ -0,0 +1,41 @@ +#ifndef EFL_UI_GRID_ITEM_PRIVATE_H +#define EFL_UI_GRID_ITEM_PRIVATE_H + +#include "Elementary.h" + +typedef struct _Efl_Ui_Grid_Item_Data +{ + // Eo Objects + Eo *obj; /* Self-Object */ + Eo *parent; /* Parent Widget */ + Eina_Rect geo; + int index; + struct { + int row; + int col; + } pos; + + /* Boolean Values */ + Eina_Bool needs_size_calc : 1; /* Flag for Size calculation */ + Eina_Bool update_me: 1; + Eina_Bool update_begin: 1; +} Efl_Ui_Grid_Item_Data; + + +#define EFL_UI_GRID_ITEM_DATA_GET(o, pd) \ + Efl_Ui_Grid_Item_Data * pd = efl_data_scope_safe_get(o, EFL_UI_GRID_ITEM_CLASS) + +#define EFL_UI_GRID_ITEM_DATA_GET_OR_RETURN(o, ptr, ...) \ + EFL_UI_GRID_ITEM_DATA_GET(o, ptr); \ + if (EINA_UNLIKELY(!ptr)) \ + { \ + ERR("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return __VA_ARGS__; \ + } + +#define EFL_UI_GRID_ITEM_CHECK_OR_RETURN(obj, ...) \ + if (EINA_UNLIKELY(!efl_isa((obj), EFL_UI_GRID_ITEM_CLASS))) \ + return __VA_ARGS__; + +#endif diff --git a/src/lib/elementary/efl_ui_grid_private.h b/src/lib/elementary/efl_ui_grid_private.h new file mode 100644 index 0000000000..a48d183639 --- /dev/null +++ b/src/lib/elementary/efl_ui_grid_private.h @@ -0,0 +1,83 @@ +#ifndef EFL_UI_GRID_PRIVATE_H +#define EFL_UI_GRID_PRIVATE_H + +#include "Elementary.h" + +typedef struct _Efl_Ui_Grid_Data +{ + // Eo Objects + Eo *obj; + Eo *pan; /* Internal pan for scroll */ + Eo *content; + Eo *smanager; /* Scroll Manager for support scroll with pan */ + Eina_Rect geo; + Eina_Position2D pre_pos; + Efl_Ui_Dir dir; + + struct { + Efl_Ui_Grid_Item *item; /* Scroll target item */ + double align; /* Item scroll aligned position. + -1 is for default case of scroll in */ + Eina_Bool anim : 1; /* boolean data for animation on scroll */ + } scroll; /* Item scroll values for deferred operation */ + + struct { + Eina_Size2D size; + Eina_Size2D pad; + struct { + double w; + double h; + } align; + int count; + int row; + int col; + } item; + + int linemax; + + Eina_List *items; /* All item list for internal maintaining */ + Eina_List *selected; /* Selected items list */ + Efl_Ui_Grid_Item *last_selected; /* latest selected item */ + + Efl_Ui_Select_Mode select_mode; /* Select mode for items + with single or multiple seleciton */ + + // Boolean Data + Eina_Bool freeze_want : 1; /* Flag for Scroll freezing */ + Eina_Bool match_content_w: 1; /* Flag for size matching on content width. + it will disable horizontal scroll */ + Eina_Bool match_content_h: 1; /* Flag for size matching on content height. + it will disable vertical scroll */ + Eina_Bool pan_resized : 1; /* Flag for pan resized. + This value is used for checking scroll is + calculated after initialized */ + Eina_Bool need_update: 1; + Eina_Bool pad_scalable: 1; +} Efl_Ui_Grid_Data; + +typedef struct _Item_Iterator +{ + Eina_Iterator iterator; + Eina_List *list; + Eina_Iterator *real_iterator; + Eo *object; +} Item_Iterator; + + +#define EFL_UI_GRID_DATA_GET(o, pd) \ + Efl_Ui_Grid_Data * pd = efl_data_scope_safe_get(o, EFL_UI_GRID_CLASS) + +#define EFL_UI_GRID_DATA_GET_OR_RETURN(o, ptr, ...) \ + EFL_UI_GRID_DATA_GET(o, ptr); \ + if (EINA_UNLIKELY(!ptr)) \ + { \ + ERR("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return __VA_ARGS__; \ + } + +#define EFL_UI_GRID_CHECK(obj) \ + if (EINA_UNLIKELY(!efl_isa((obj), EFL_UI_GRID_CLASS))) \ + return + +#endif diff --git a/src/lib/elementary/efl_ui_list_default_item_part_icon.eo b/src/lib/elementary/efl_ui_list_default_item_part_icon.eo index b3359eb595..319be19fe3 100644 --- a/src/lib/elementary/efl_ui_list_default_item_part_icon.eo +++ b/src/lib/elementary/efl_ui_list_default_item_part_icon.eo @@ -6,4 +6,4 @@ class Efl.Ui.List_Default_Item_Part_Icon (Efl.Ui.Layout_Part, Efl.Content) Efl.Content.content { get; set; } Efl.Content.content_unset; } -} \ No newline at end of file +} diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build index 3420684b3f..daf89bb085 100644 --- a/src/lib/elementary/meson.build +++ b/src/lib/elementary/meson.build @@ -216,6 +216,11 @@ pub_eo_files = [ 'efl_ui_list_default_item.eo', 'efl_ui_list_empty_item.eo', 'efl_ui_list.eo', + 'efl_ui_grid_item.eo', + 'efl_ui_grid_default_item_part_icon.eo', + 'efl_ui_grid_default_item_part_end.eo', + 'efl_ui_grid_default_item.eo', + 'efl_ui_grid.eo', 'efl_ui_panes_part.eo', 'efl_ui_progressbar_part.eo', 'elm_slider.eo', @@ -441,6 +446,8 @@ elementary_headers_unstable = [ 'efl_ui_item_private.h', 'efl_ui_list_item_private.h', 'efl_ui_list_private.h', + 'efl_ui_grid_item_private.h', + 'efl_ui_grid_private.h', 'efl_ui_list_view_private.h', 'efl_ui_list_view_seg_array.h', 'elm_widget_web.h', @@ -866,6 +873,9 @@ elementary_src = [ 'efl_ui_list_default_item.c', 'efl_ui_list_empty_item.c', 'efl_ui_list.c', + 'efl_ui_grid_item.c', + 'efl_ui_grid_default_item.c', + 'efl_ui_grid.c', 'efl_ui_list_view.c', 'efl_ui_list_view_precise_layouter.c', 'efl_ui_list_view_seg_array.c', diff --git a/src/tests/elementary/efl_ui_test_grid.c b/src/tests/elementary/efl_ui_test_grid.c new file mode 100644 index 0000000000..a6975ab262 --- /dev/null +++ b/src/tests/elementary/efl_ui_test_grid.c @@ -0,0 +1,338 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define EFL_ACCESS_OBJECT_BETA +#include +#include "elm_suite.h" + +static Eo *win, *box; +static Efl_Ui_Grid *grid; + +static void +grid_setup() +{ + //win = win_add(); + win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(), + efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC), + efl_text_set(efl_added, "Efl.Ui.Grid"), + efl_ui_win_autodel_set(efl_added, EINA_TRUE)); + box = efl_add(EFL_UI_BOX_CLASS, win, + efl_ui_direction_set(efl_added, EFL_UI_DIR_VERTICAL)); + efl_gfx_size_hint_weight_set(box, EFL_GFX_SIZE_HINT_EXPAND, EFL_GFX_SIZE_HINT_EXPAND); + efl_gfx_size_hint_align_set(box, EFL_GFX_SIZE_HINT_FILL, EFL_GFX_SIZE_HINT_FILL); + elm_win_resize_object_add(win, box); + + grid = efl_add(EFL_UI_GRID_CLASS, box); + + efl_ui_grid_item_size_set(grid, EINA_SIZE2D(100, 100)); + efl_pack_padding_set(grid, 5.0, 5.0, EINA_TRUE); + efl_pack_align_set(grid, 0.5, 0.5); + efl_pack_end(box, grid); + + efl_gfx_entity_size_set(win, EINA_SIZE2D(500, 500)); +} + +static void +grid_teardown() +{ + if (grid) + { + efl_del(grid); + grid = NULL; + } + if (win) + { + efl_del(win); + win = NULL; + } +} + +static Eina_Bool +grid_item_pack(Eo *grid, int count, Eina_List **l) +{ + int i; + Efl_Ui_Grid_Item *item; + for (i = 0; i < count; i++) + { + item = efl_add(EFL_UI_GRID_DEFAULT_ITEM_CLASS, grid); + if (!item) return EINA_FALSE; + if (l) *l = eina_list_append(*l, item); + efl_pack(grid, item); + } + return EINA_TRUE; +} + +EFL_START_TEST (efl_ui_grid_class_check) +{ + const char *class; + + class = efl_class_name_get(grid); + + ck_assert(class != NULL); + ck_assert(!strcmp(class, "Efl.Ui.Grid")); +} +EFL_END_TEST + +EFL_START_TEST (efl_ui_grid_pack) +{ + Efl_Ui_Grid_Item *item; + int count; + + item = efl_add(EFL_UI_GRID_DEFAULT_ITEM_CLASS, grid); + efl_pack(grid, item); + + count = efl_content_count(grid); + + ck_assert(count == 1); +} +EFL_END_TEST + +EFL_START_TEST (efl_ui_grid_unpack) +{ + Efl_Ui_Grid_Item *item; + int count; + + item = efl_add(EFL_UI_GRID_DEFAULT_ITEM_CLASS, grid); + efl_pack(grid, item); + + efl_pack_unpack(grid, item); + + count = efl_content_count(grid); + ck_assert(count == 0); + + efl_del(item); +} +EFL_END_TEST + +EFL_START_TEST (efl_ui_grid_unpack_all) +{ + Efl_Ui_Grid_Item *item; + int count_before = 10; + int count; + Eina_Iterator *itor; + + ck_assert(grid_item_pack(grid, count_before, NULL) != EINA_FALSE); + + itor = efl_content_iterate(grid); + efl_pack_unpack_all(grid); + + count = efl_content_count(grid); + ck_assert(count == 0); + + EINA_ITERATOR_FOREACH(itor, item) + efl_del(item); + + free(itor); +} +EFL_END_TEST + +EFL_START_TEST (efl_ui_grid_pack_clear) +{ + int count_before = 10; + int count; + + ck_assert(grid_item_pack(grid, count_before, NULL) != EINA_FALSE); + + efl_pack_clear(grid); + + count = efl_content_count(grid); + ck_assert(count == 0); +} +EFL_END_TEST + + +EFL_START_TEST (efl_ui_grid_pack_end) +{ + Efl_Ui_Grid_Item *item, *compare; + int count_before = 10; + int count; + + ck_assert(grid_item_pack(grid, count_before, NULL) != EINA_FALSE); + + item = efl_add(EFL_UI_GRID_DEFAULT_ITEM_CLASS, grid); + ck_assert(item != NULL); + efl_pack_end(grid, item); + + count = efl_content_count(grid); + ck_assert(count == (count_before + 1)); + + compare = efl_pack_content_get(grid, (count - 1)); + ck_assert(compare != NULL); + ck_assert(item == compare); +} +EFL_END_TEST + +EFL_START_TEST (efl_ui_grid_pack_begin) +{ + Efl_Ui_Grid_Item *item, *compare; + int count_before = 10; + int count; + + ck_assert(grid_item_pack(grid, count_before, NULL) != EINA_FALSE); + + item = efl_add(EFL_UI_GRID_DEFAULT_ITEM_CLASS, grid); + ck_assert(item != NULL); + efl_pack_begin(grid, item); + + count = efl_content_count(grid); + ck_assert(count == (count_before + 1)); + + compare = efl_pack_content_get(grid, 0); + ck_assert(compare != NULL); + ck_assert(item == compare); +} +EFL_END_TEST + +EFL_START_TEST (efl_ui_grid_pack_after) +{ + Efl_Ui_Grid_Item *item, *after, *compare; + int count_before = 10; + int count; + int index = 5; + + ck_assert(grid_item_pack(grid, count_before, NULL) != EINA_FALSE); + + after = efl_pack_content_get(grid, index); + ck_assert(after != NULL); + + item = efl_add(EFL_UI_GRID_DEFAULT_ITEM_CLASS, grid); + ck_assert(item != NULL); + efl_pack_after(grid, item, after); + + count = efl_content_count(grid); + ck_assert(count == (count_before + 1)); + + compare = efl_pack_content_get(grid, index + 1); + ck_assert(compare != NULL); + ck_assert(item == compare); +} +EFL_END_TEST + +EFL_START_TEST (efl_ui_grid_pack_before) +{ + Efl_Ui_Grid_Item *item, *before, *compare; + int count_before = 10; + int count; + int index = 5; + + ck_assert(grid_item_pack(grid, count_before, NULL) != EINA_FALSE); + + before = efl_pack_content_get(grid, index); + ck_assert(before != NULL); + + item = efl_add(EFL_UI_GRID_DEFAULT_ITEM_CLASS, grid); + ck_assert(item != NULL); + efl_pack_before(grid, item, before); + + count = efl_content_count(grid); + ck_assert(count == (count_before + 1)); + + compare = efl_pack_content_get(grid, index); + ck_assert(compare != NULL); + ck_assert(item == compare); +} +EFL_END_TEST + +EFL_START_TEST (efl_ui_grid_content_count) +{ + int count = 10, compare; + + ck_assert(grid_item_pack(grid, count, NULL) != EINA_FALSE); + + compare = efl_content_count(grid); + + ck_assert(count == compare); +} +EFL_END_TEST + +EFL_START_TEST (efl_ui_grid_content_iterate) +{ + int count = 10; + Efl_Ui_Grid_Item *item; + Eina_List *item_list = NULL; + Eina_Iterator *item_itr; + + ck_assert(grid_item_pack(grid, count, &item_list) != EINA_FALSE); + + /* Get Item Content Iterator */ + item_itr = efl_content_iterate(grid); + + EINA_ITERATOR_FOREACH(item_itr, item) + { + /* Compare the iterator data and list data */ + ck_assert(item == eina_list_data_get(item_list)); + item_list = eina_list_remove(item_list, item); + } + eina_iterator_free(item_itr); + + ck_assert(item_list == NULL); +} +EFL_END_TEST + + +int tcount = 0; + +static void +grid_timer_cb(void *data EINA_UNUSED, const Efl_Event *event) +{ + ck_assert(0); + efl_del(event->object); + ecore_main_loop_quit(); +} + +static void +grid_scroll_start_cb(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED) +{ + //printf("LSH :: scroll start!!!\n"); +} + +static void +grid_scroll_stop_cb(void *data, const Efl_Event *event EINA_UNUSED) +{ + Efl_Loop_Timer *timer = data; + efl_del(timer); + ecore_main_loop_quit(); +} + +EFL_CALLBACKS_ARRAY_DEFINE(grid_scroll_callbacks, + { EFL_UI_EVENT_SCROLL_START, grid_scroll_start_cb }, + { EFL_UI_EVENT_SCROLL_STOP, grid_scroll_stop_cb }); + +EFL_START_TEST (efl_ui_grid_scroll) +{ + Efl_Ui_Grid_Item *item; + Efl_Loop_Timer *timer; + + ck_assert(grid_item_pack(grid, 100, NULL) != EINA_FALSE); + item = efl_pack_content_get(grid, 50); + + timer = efl_add(EFL_LOOP_TIMER_CLASS, efl_main_loop_get(), + efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TICK, grid_timer_cb, NULL), + efl_loop_timer_loop_reset(efl_added), + efl_loop_timer_interval_set(efl_added, 3.0)); + + efl_event_callback_array_add(grid, grid_scroll_callbacks(), timer); + /*FIXME: efl_ui_scroll_interface only emit scroll event when animation exist */ + efl_ui_grid_item_scroll(grid, item, EINA_TRUE); + ecore_main_loop_begin(); +} +EFL_END_TEST + + +void efl_ui_test_grid(TCase *tc) +{ + tcase_add_checked_fixture(tc, grid_setup, grid_teardown); + tcase_add_test(tc, efl_ui_grid_class_check); + tcase_add_test(tc, efl_ui_grid_pack); + tcase_add_test(tc, efl_ui_grid_unpack); + tcase_add_test(tc, efl_ui_grid_unpack_all); + tcase_add_test(tc, efl_ui_grid_pack_clear); + tcase_add_test(tc, efl_ui_grid_pack_end); + tcase_add_test(tc, efl_ui_grid_pack_begin); + tcase_add_test(tc, efl_ui_grid_pack_after); + tcase_add_test(tc, efl_ui_grid_pack_before); + tcase_add_test(tc, efl_ui_grid_content_count); + tcase_add_test(tc, efl_ui_grid_content_iterate); + tcase_add_test(tc, efl_ui_grid_scroll); +} diff --git a/src/tests/elementary/elm_suite.c b/src/tests/elementary/elm_suite.c index 198179b880..a4914e0ae8 100644 --- a/src/tests/elementary/elm_suite.c +++ b/src/tests/elementary/elm_suite.c @@ -89,6 +89,10 @@ static const Efl_Test_Case etc[] = { { "elm_code_widget_undo", elm_code_test_widget_undo }, { "elm_focus", elm_test_focus}, { "elm_focus_sub", elm_test_focus_sub}, +/* FIXME : This test must move efl_ui_suite when it ready * + * EFL_UI_TEST BEGIN */ + { "efl_ui_grid", efl_ui_test_grid}, +/* EFL_UI_TEST END */ { NULL, NULL } }; diff --git a/src/tests/elementary/elm_suite.h b/src/tests/elementary/elm_suite.h index ea291376f9..f5e699b9cb 100644 --- a/src/tests/elementary/elm_suite.h +++ b/src/tests/elementary/elm_suite.h @@ -83,6 +83,10 @@ void elm_test_spinner(TCase *tc); void elm_test_plug(TCase *tc); void elm_test_focus(TCase *tc); void elm_test_focus_sub(TCase *tc); +/* FIXME : This test must move efl_ui_suite when it ready * + * EFL_UI_TEST BEGIN */ +void efl_ui_test_grid(TCase *tc); +/* EFL_UI_TEST END */ void elm_code_file_test_load(TCase *tc); void elm_code_file_test_memory(TCase *tc); diff --git a/src/tests/elementary/meson.build b/src/tests/elementary/meson.build index b6073af73d..f63b7ace06 100644 --- a/src/tests/elementary/meson.build +++ b/src/tests/elementary/meson.build @@ -99,7 +99,8 @@ elementary_suite_src = [ 'elm_test_focus_common.c', 'elm_test_focus_common.h', 'elm_test_focus.c', - 'elm_test_focus_sub.c' + 'elm_test_focus_sub.c', + 'efl_ui_test_grid.c' ] elementary_suite = executable('elementary_suite',