1 #ifndef EFL_UI_RELATIVE_CONTAINER_PRIVATE_H 2 #define EFL_UI_RELATIVE_CONTAINER_PRIVATE_H 3 4 #ifdef HAVE_CONFIG_H 5 # include "elementary_config.h" 6 #endif 7 8 #define EFL_PACK_LAYOUT_PROTECTED 9 10 #include <Elementary.h> 11 #include "elm_priv.h" 12 13 typedef enum _Efl_Ui_Relative_Container_Calc_State 14 { 15 RELATIVE_CALC_NONE, 16 RELATIVE_CALC_DONE, 17 RELATIVE_CALC_ON 18 } Efl_Ui_Relative_Container_Calc_State; 19 20 typedef struct _Efl_Ui_Relative_Container_Data Efl_Ui_Relative_Container_Data; 21 typedef struct _Efl_Ui_Relative_Container_Child Efl_Ui_Relative_Container_Child; 22 typedef struct _Efl_Ui_Relative_Container_Calc Efl_Ui_Relative_Container_Calc; 23 typedef struct _Efl_Ui_Relative_Container_Relation Efl_Ui_Relative_Container_Relation; 24 typedef struct _Efl_Ui_Relative_Container_Content_Iterator Efl_Ui_Relative_Container_Content_Iterator; 25 26 struct _Efl_Ui_Relative_Container_Calc 27 { 28 EINA_INLIST; 29 30 int max[2]; 31 int min[2]; 32 int aspect[2]; 33 int margin[4]; 34 Efl_Gfx_Hint_Aspect aspect_type; 35 Eina_Bool fill[2]; 36 double weight[2]; 37 double align[2]; 38 double comp_factor; 39 /* m0 is static min size which is added to the other children min size. 40 * only if both (target, relative)[0] and (target, relative)[1] are same, 41 * it has non-zero value. it is calculated as (min * (align / relative)) if 42 * align is greater than relative, (min * ((1 - align) / (1 - relative))) otherwise. 43 * mi, mj are transformed relative based on layout min size. they are 44 * calculated as (target.mi + (relative * (target.mj - target.mi))). for example, 45 * there are two children of relative_container that has different target base. 46 * | | obj1 | obj2 | 47 * | min | 100 | 100 | 48 * |left.target | layout| obj1 | 49 * |left.relative | 0.0 | 0.5 | 50 * |right.target | layout| obj1 | 51 * |right.relative| 0.5 | 1.0 | 52 * | mi | 0.0 | 0.25 | 53 * | mj | 0.5 | 0.5 | 54 * 55 * obj1.mi = layout.mi(0.0) + (obj1.relative(0.0) * (LAyout.mj(1.0) - layout.mi(0.0))) = 0.0 56 * obj1.mj = layout.mi(0.0) + (obj1.relative(0.5) * (layout.mj(1.0) - layout.mi(0.0))) = 0.5 57 * obj2.mi = obj1.mi(0.0) + (obj2.relative(0.5) * (obj1.mj(0.5) - obj1.mi(0.0))) = 0.25 58 * obj2.mj = obj1.mi(0.0) + (obj2.relative(1.0) * (obj1.mj(0.5) - obj1.mi(0.0))) = 0.5 59 * layout min size is calculated as maximum of (child_min + m0) / (mj - mi). 60 * in the example, obj1 require layout min size as 61 * ((child_min(100) + m0(0)) / (mj(0.5) - mi(0.0))) = 200. obj2 require 62 * layout min size as ((100 + 0) / (0.5 - 0.25)) = 400. as a result, layout 63 * min size is max(200, 400) = 400. 64 */ 65 double m0[2]; 66 double mi[2], mj[2]; 67 68 struct { 69 int position; 70 double length; 71 } space[2], want[2]; 72 73 Efl_Ui_Relative_Container_Calc_State state[2]; 74 Efl_Ui_Relative_Container_Calc_State chain_state[2]; 75 Efl_Ui_Relative_Container_Child *to[4]; 76 }; 77 78 struct _Efl_Ui_Relative_Container_Data 79 { 80 Eo *obj; 81 Eo *clipper; 82 Eina_Hash *children; 83 Efl_Ui_Relative_Container_Child *base; 84 }; 85 86 struct _Efl_Ui_Relative_Container_Relation 87 { 88 Efl_Object *to; 89 double relative_position; 90 }; 91 92 struct _Efl_Ui_Relative_Container_Child 93 { 94 Eo *obj; 95 Eo *layout; 96 Efl_Ui_Relative_Container_Relation rel[4]; 97 Efl_Ui_Relative_Container_Calc calc; 98 }; 99 100 struct _Efl_Ui_Relative_Container_Content_Iterator 101 { 102 Eina_Iterator iterator; 103 Eina_Iterator *real_iterator; 104 Eo *relative_container; 105 }; 106 107 #define EFL_UI_RELATIVE_CONTAINER_RELATION_SET_GET(direction, DIRECTION) \ 108 EOLIAN static void \ 109 _efl_ui_relative_container_relation_ ## direction ## _set(Eo *obj, Efl_Ui_Relative_Container_Data *pd, Eo *child, Eo *target, double relative_position) \ 110 { \ 111 Efl_Ui_Relative_Container_Child *rc; \ 112 if (!child) return; \ 113 rc = _relative_child_get(pd, child); \ 114 if (!rc) return; \ 115 if (target) rc->rel[DIRECTION].to = target; \ 116 if (relative_position < 0) relative_position = 0; \ 117 else if (relative_position > 1) relative_position = 1; \ 118 rc->rel[DIRECTION].relative_position = relative_position; \ 119 efl_pack_layout_request(obj); \ 120 } \ 121 \ 122 EOLIAN static void \ 123 _efl_ui_relative_container_relation_ ## direction ## _get(const Eo *obj EINA_UNUSED, Efl_Ui_Relative_Container_Data *pd, Eo *child, Eo **target, double *relative_position) \ 124 { \ 125 Efl_Ui_Relative_Container_Child *rc; \ 126 Eo *rel_to = NULL; \ 127 double rel_relative = 0.0; \ 128 rc = eina_hash_find(pd->children, &child); \ 129 if (rc) \ 130 { \ 131 rel_to = rc->rel[DIRECTION].to; \ 132 rel_relative = rc->rel[DIRECTION].relative_position; \ 133 } \ 134 else \ 135 ERR("child(%p(%s)) is not registered", child, efl_class_name_get(child)); \ 136 if (target) *target = rel_to; \ 137 if (relative_position) *relative_position = rel_relative; \ 138 } 139 140 #endif 141