diff --git a/src/bin/elementary/test_ui_box.c b/src/bin/elementary/test_ui_box.c index 3d5a2c23e3..ba83b55d42 100644 --- a/src/bin/elementary/test_ui_box.c +++ b/src/bin/elementary/test_ui_box.c @@ -200,13 +200,13 @@ static const Eo_Class_Description custom_engine_class_desc = { EO_CLASS_DESCRIPTION_OPS(custom_engine_op_desc), NULL, 0, NULL, NULL }; -EO_DEFINE_CLASS(custom_engine_class_get, &custom_engine_class_desc, EFL_PACK_ENGINE_INTERFACE, NULL) +EO_DEFINE_CLASS(_test_ui_box_custom_engine_class_get, &custom_engine_class_desc, EFL_PACK_ENGINE_INTERFACE, NULL) static Eina_Bool custom_check_cb(void *data, const Eo_Event *event) { Eina_Bool chk = elm_check_selected_get(event->obj); - efl_pack_layout_engine_set(data, chk ? custom_engine_class_get() : NULL, NULL); + efl_pack_layout_engine_set(data, chk ? _test_ui_box_custom_engine_class_get() : NULL, NULL); return EO_CALLBACK_CONTINUE; } diff --git a/src/bin/elementary/test_ui_grid.c b/src/bin/elementary/test_ui_grid.c index c2745269e3..2d261f706e 100644 --- a/src/bin/elementary/test_ui_grid.c +++ b/src/bin/elementary/test_ui_grid.c @@ -10,47 +10,68 @@ typedef enum { NONE_BUT_FILL, EQUAL, ONE, - TWO + TWO, + CUSTOM } Weight_Mode; -#define P(i) ((void*)(intptr_t)i) -#define I(p) ((int)(intptr_t)p) +static void _custom_engine_layout_do(Eo *obj, void *pd, Efl_Pack *pack, const void *data); + +/* Common Eo Class boilerplate. */ +static const Eo_Op_Description custom_engine_op_desc[] = { + EO_OP_CLASS_FUNC_OVERRIDE(efl_pack_engine_layout_do, _custom_engine_layout_do), +}; + +static const Eo_Class_Description custom_engine_class_desc = { + EO_VERSION, "Custom Layout Engine", EO_CLASS_TYPE_INTERFACE, + EO_CLASS_DESCRIPTION_OPS(custom_engine_op_desc), NULL, 0, NULL, NULL +}; + +EO_DEFINE_CLASS(_test_ui_grid_custom_engine_class_get, &custom_engine_class_desc, EFL_PACK_ENGINE_INTERFACE, NULL) + +#define CUSTOM_ENGINE_CLASS _test_ui_grid_custom_engine_class_get() static Eina_Bool weights_cb(void *data, const Eo_Event *event) { Weight_Mode mode = elm_radio_state_value_get(event->obj); + Eo *grid = data; + + if (mode != CUSTOM) + efl_pack_layout_engine_set(grid, NULL, NULL); switch (mode) { case NONE: - evas_object_size_hint_align_set(data, 0.5, 0.5); + evas_object_size_hint_align_set(grid, 0.5, 0.5); for (int i = 0; i < 7; i++) evas_object_size_hint_weight_set(objects[i], 0, 0); break; case NONE_BUT_FILL: - evas_object_size_hint_align_set(data, -1, -1); + evas_object_size_hint_align_set(grid, -1, -1); for (int i = 0; i < 7; i++) evas_object_size_hint_weight_set(objects[i], 0, 0); break; case EQUAL: - evas_object_size_hint_align_set(data, 0.5, 0.5); + evas_object_size_hint_align_set(grid, 0.5, 0.5); for (int i = 0; i < 7; i++) evas_object_size_hint_weight_set(objects[i], 1, 1); break; case ONE: - evas_object_size_hint_align_set(data, 0.5, 0.5); + evas_object_size_hint_align_set(grid, 0.5, 0.5); for (int i = 0; i < 6; i++) evas_object_size_hint_weight_set(objects[i], 0, 0); evas_object_size_hint_weight_set(objects[6], 1, 1); break; case TWO: - evas_object_size_hint_align_set(data, 0.5, 0.5); + evas_object_size_hint_align_set(grid, 0.5, 0.5); for (int i = 0; i < 5; i++) evas_object_size_hint_weight_set(objects[i], 0, 0); evas_object_size_hint_weight_set(objects[5], 1, 1); evas_object_size_hint_weight_set(objects[6], 1, 1); break; + case CUSTOM: + efl_pack_layout_engine_set(grid, CUSTOM_ENGINE_CLASS, NULL); + break; } return EO_CALLBACK_CONTINUE; @@ -123,6 +144,49 @@ child_evt_cb(void *data, const Eo_Event *event) return EO_CALLBACK_CONTINUE; } +static void +_custom_engine_layout_do(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, + Efl_Pack *pack, const void *data EINA_UNUSED) +{ + /* Example custom layout for grid: + * divide space into regions of same size, place objects in center of their + * cells using their min size + * Note: This is a TERRIBLE layout function (disregards align, weight, ...) + */ + + int rows, cols, gw, gh, gx, gy, c, r, cs, rs, gmw = 0, gmh = 0; + Eina_Iterator *it; + Eo *item; + + efl_gfx_size_get(pack, &gw, &gh); + efl_gfx_position_get(pack, &gx, &gy); + + efl_pack_grid_size_get(pack, &cols, &rows); + if (!cols || !rows) goto end; + + it = efl_pack_contents_iterate(pack); + EINA_ITERATOR_FOREACH(it, item) + { + if (efl_pack_child_position_get(pack, item, &c, &r, &cs, &rs)) + { + int x, y, mw, mh; + + evas_object_size_hint_min_get(item, &mw, &mh); + x = gx + c * gw / cols + (cs * gw / cols - mw) / 2; + y = gy + r * gh / rows + (rs * gh / rows - mh) / 2; + efl_gfx_size_set(item, mw, mh); + efl_gfx_position_set(item, x, y); + + gmw = MAX(gmw, mw); + gmh = MAX(gmh, mh); + } + } + eina_iterator_free(it); + +end: + evas_object_size_hint_min_set(pack, gmw * cols, gmh * rows); +} + void test_ui_grid(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { @@ -211,6 +275,15 @@ test_ui_grid(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_i efl_pack(bx, o); efl_gfx_visible_set(o, 1); + o = elm_radio_add(win); + elm_object_text_set(o, "Custom layout"); + eo_event_callback_add(o, ELM_RADIO_EVENT_CHANGED, weights_cb, grid); + evas_object_size_hint_align_set(o, 0, 0.5); + elm_radio_state_value_set(o, CUSTOM); + elm_radio_group_add(o, chk); + efl_pack(bx, o); + efl_gfx_visible_set(o, 1); + elm_radio_value_set(chk, EQUAL); diff --git a/src/lib/efl/interfaces/efl_pack_grid.eo b/src/lib/efl/interfaces/efl_pack_grid.eo index a4ea673ede..2ca2c0d5d0 100644 --- a/src/lib/efl/interfaces/efl_pack_grid.eo +++ b/src/lib/efl/interfaces/efl_pack_grid.eo @@ -36,7 +36,7 @@ interface Efl.Pack_Grid (Efl.Pack_Linear) @property pack_child_position { [[position and span of the $subobj in this container, may be modified to move the $subobj]] set { [[same as grid_pack]] } - get {} + get { return: bool; [[returns false if item is not a child]] } keys { subobj: Efl.Pack_Item*; } diff --git a/src/lib/elementary/efl_ui_box.c b/src/lib/elementary/efl_ui_box.c index cd9e3e48a8..79fb089972 100644 --- a/src/lib/elementary/efl_ui_box.c +++ b/src/lib/elementary/efl_ui_box.c @@ -148,16 +148,6 @@ _evas_box_custom_layout(Evas_Object *evas_box EINA_UNUSED, efl_pack_layout_update(obj); } -static void -_layout_do(Efl_Ui_Box *obj) -{ - ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); - Evas_Object_Box_Data *bd; - - bd = eo_data_scope_get(wd->resize_obj, EVAS_BOX_CLASS); - _efl_ui_box_custom_layout(obj, bd); -} - EOLIAN static void _efl_ui_box_efl_pack_layout_update(Eo *obj, Efl_Ui_Box_Data *pd) { @@ -170,7 +160,11 @@ _efl_ui_box_efl_pack_engine_layout_do(Eo *klass EINA_UNUSED, void *_pd EINA_UNUSED, Eo *obj, const void *data EINA_UNUSED) { - _layout_do(obj); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + Evas_Object_Box_Data *bd; + + bd = eo_data_scope_get(wd->resize_obj, EVAS_BOX_CLASS); + _efl_ui_box_custom_layout(obj, bd); } EOLIAN static Eina_Bool diff --git a/src/lib/elementary/efl_ui_grid.c b/src/lib/elementary/efl_ui_grid.c index 3b0e7ce810..b8a7ee06a2 100644 --- a/src/lib/elementary/efl_ui_grid.c +++ b/src/lib/elementary/efl_ui_grid.c @@ -8,6 +8,7 @@ #include "elm_priv.h" #include "efl_ui_grid.eo.h" +#include "../evas/canvas/evas_table.eo.h" #define MY_CLASS EFL_UI_GRID_CLASS #define MY_CLASS_NAME "Efl.Ui.Grid" @@ -15,6 +16,7 @@ typedef struct _Efl_Ui_Grid_Data Efl_Ui_Grid_Data; typedef struct _Grid_Item_Iterator Grid_Item_Iterator; typedef struct _Grid_Item Grid_Item; +typedef struct _Custom_Table_Data Custom_Table_Data; static Eina_Bool _subobj_del_cb(void *data, const Eo_Event *event); static void _item_remove(Efl_Ui_Grid *obj, Efl_Ui_Grid_Data *pd, Efl_Pack_Item *subobj); @@ -34,6 +36,9 @@ struct _Grid_Item struct _Efl_Ui_Grid_Data { + const Eo_Class *layout_engine; + const void *layout_data; + Grid_Item *items; int count; @@ -49,12 +54,18 @@ struct _Efl_Ui_Grid_Data struct _Grid_Item_Iterator { - Eina_List *list; Eina_Iterator iterator; Eina_Iterator *real_iterator; + Eina_List *list; Efl_Ui_Grid *object; }; +struct _Custom_Table_Data +{ + Efl_Ui_Grid *parent; + Efl_Ui_Grid_Data *gd; +}; + static const Eo_Callback_Array_Item subobj_callbacks [] = { { EO_BASE_EVENT_DEL, _subobj_del_cb }, { NULL, NULL } @@ -173,7 +184,6 @@ _efl_ui_grid_elm_widget_theme_apply(Eo *obj, Efl_Ui_Grid_Data *pd EINA_UNUSED) static void _layout_updated_emit(Efl_Ui_Grid *obj) { - /* FIXME: can't be called properly since there is no smart calc event */ eo_event_callback_call(obj, EFL_PACK_EVENT_LAYOUT_UPDATED, NULL); } @@ -197,7 +207,6 @@ _sizing_eval(Evas_Object *obj, Efl_Ui_Grid_Data *pd EINA_UNUSED) if ((maxw >= 0) && (w > maxw)) w = maxw; if ((maxh >= 0) && (h > maxh)) h = maxh; evas_object_resize(obj, w, h); - _layout_updated_emit(obj); } static void @@ -210,14 +219,93 @@ _table_size_hints_changed(void *data, Evas *e EINA_UNUSED, _sizing_eval(data, pd); } -EOLIAN static void -_efl_ui_grid_evas_object_smart_add(Eo *obj, Efl_Ui_Grid_Data *pd EINA_UNUSED) +/* Custom table class: overrides smart_calculate. */ +static void _custom_table_calc(Eo *obj, Custom_Table_Data *pd); + +static const Eo_Op_Description custom_table_op_desc[] = { + EO_OP_CLASS_FUNC_OVERRIDE(evas_obj_smart_calculate, _custom_table_calc), +}; + +static const Eo_Class_Description custom_table_class_desc = { + EO_VERSION, "Efl.Ui.Grid.Internal", EO_CLASS_TYPE_REGULAR, + EO_CLASS_DESCRIPTION_OPS(custom_table_op_desc), NULL, + sizeof(Custom_Table_Data), NULL, NULL +}; + +EO_DEFINE_CLASS(_efl_ui_grid_custom_table_class_get, &custom_table_class_desc, + EVAS_TABLE_CLASS, NULL) + +#define CUSTOM_TABLE_CLASS _efl_ui_grid_custom_table_class_get() + +static void +_custom_table_calc(Eo *obj, Custom_Table_Data *pd) { + int cols, rows; + + evas_object_table_col_row_size_get(obj, &cols, &rows); + if ((cols < 1) || (rows < 1)) return; + + efl_pack_layout_update(pd->parent); + _layout_updated_emit(pd->parent); +} +/* End of custom table class */ + +EOLIAN Eina_Bool +_efl_ui_grid_efl_pack_layout_engine_set(Eo *obj, Efl_Ui_Grid_Data *pd, const Eo_Class *engine, const void *data) +{ + pd->layout_engine = engine ? engine : eo_class_get(obj); + pd->layout_data = data; + efl_pack_layout_request(obj); + return EINA_TRUE; +} + +EOLIAN void +_efl_ui_grid_efl_pack_layout_engine_get(Eo *obj EINA_UNUSED, Efl_Ui_Grid_Data *pd, const Eo_Class **engine, const void **data) +{ + if (engine) *engine = pd->layout_engine; + if (data) *data = pd->layout_data; +} + +EOLIAN static void +_efl_ui_grid_efl_pack_layout_update(Eo *obj, Efl_Ui_Grid_Data *pd) +{ + _sizing_eval(obj, pd); + efl_pack_engine_layout_do(pd->layout_engine, obj, pd->layout_data); +} + +EOLIAN static void +_efl_ui_grid_efl_pack_engine_layout_do(Eo *klass EINA_UNUSED, + void *_pd EINA_UNUSED, + Eo *obj, const void *data EINA_UNUSED) +{ + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + evas_obj_smart_calculate(eo_super(wd->resize_obj, CUSTOM_TABLE_CLASS)); +} + +EOLIAN void +_efl_ui_grid_evas_object_smart_calculate(Eo *obj, Efl_Ui_Grid_Data *pd EINA_UNUSED) +{ + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + efl_pack_layout_update(obj); +} + +EOLIAN static void +_efl_ui_grid_evas_object_smart_add(Eo *obj, Efl_Ui_Grid_Data *pd) +{ + Custom_Table_Data *custom; Evas_Object *table; + pd->layout_engine = MY_CLASS; + elm_widget_sub_object_parent_add(obj); - table = evas_object_table_add(evas_object_evas_get(obj)); + table = eo_add(CUSTOM_TABLE_CLASS, obj); + custom = eo_data_scope_get(table, CUSTOM_TABLE_CLASS); + custom->gd = pd; + custom->parent = obj; + evas_object_table_homogeneous_set(table, EVAS_OBJECT_TABLE_HOMOGENEOUS_TABLE); elm_widget_resize_object_set(obj, table, EINA_TRUE); @@ -276,6 +364,8 @@ _efl_ui_grid_eo_base_constructor(Eo *obj, Efl_Ui_Grid_Data *pd) return obj; } + + EOLIAN static void _efl_ui_grid_efl_pack_padding_set(Eo *obj, Efl_Ui_Grid_Data *pd EINA_UNUSED, double h, double v, Eina_Bool scalable) { @@ -408,11 +498,12 @@ _efl_ui_grid_efl_pack_grid_pack_child_position_set(Eo *obj, Efl_Ui_Grid_Data *pd _pack_at(obj, pd, subobj, col, row, colspan, rowspan, EINA_FALSE); } -EOLIAN static void +EOLIAN static Eina_Bool _efl_ui_grid_efl_pack_grid_pack_child_position_get(Eo *obj, Efl_Ui_Grid_Data *pd EINA_UNUSED, Evas_Object *subobj, int *col, int *row, int *colspan, int *rowspan) { int c = -1, r = -1, cs = 0, rs = 0; Grid_Item *gi; + Eina_Bool ret = EINA_FALSE; if (obj != elm_widget_parent_widget_get(subobj)) { @@ -429,11 +520,14 @@ _efl_ui_grid_efl_pack_grid_pack_child_position_get(Eo *obj, Efl_Ui_Grid_Data *pd rs = gi->row_span; } + ret = EINA_TRUE; + end: if (col) *col = c; if (row) *row = r; if (colspan) *colspan = cs; if (rowspan) *rowspan = rs; + return ret; } EOLIAN static Efl_Pack_Item * @@ -533,21 +627,6 @@ _efl_ui_grid_efl_pack_unpack_all(Eo *obj, Efl_Ui_Grid_Data *pd EINA_UNUSED) evas_object_table_clear(wd->resize_obj, EINA_FALSE); } -EOLIAN void -_efl_ui_grid_evas_object_smart_calculate(Eo *obj, Efl_Ui_Grid_Data *pd EINA_UNUSED) -{ - ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); - - evas_object_smart_calculate(wd->resize_obj); -} - -EOLIAN void -_efl_ui_grid_efl_pack_layout_update(Eo *obj, Efl_Ui_Grid_Data *pd) -{ - _sizing_eval(obj, pd); - _layout_updated_emit(obj); -} - EOLIAN void _efl_ui_grid_efl_pack_layout_request(Eo *obj, Efl_Ui_Grid_Data *pd EINA_UNUSED) { diff --git a/src/lib/elementary/efl_ui_grid.eo b/src/lib/elementary/efl_ui_grid.eo index 9a32f427b2..839d7a24a9 100644 --- a/src/lib/elementary/efl_ui_grid.eo +++ b/src/lib/elementary/efl_ui_grid.eo @@ -1,7 +1,5 @@ -class Efl.Ui.Grid (Elm.Widget, Efl.Pack_Grid) +class Efl.Ui.Grid (Elm.Widget, Efl.Pack_Grid, Efl.Pack_Engine) { - methods { - } implements { Eo.Base.constructor; @@ -41,5 +39,9 @@ class Efl.Ui.Grid (Elm.Widget, Efl.Pack_Grid) Efl.Pack_Linear.pack_end; Efl.Pack_Linear.direction.set; Efl.Pack_Linear.direction.get; + + Efl.Pack.layout_engine.get; + Efl.Pack.layout_engine.set; + Efl.Pack_Engine.layout_do; } }