efl/src/lib/elementary/efl_ui_relative_layout_priv...

141 lines
5.0 KiB
C

#ifndef EFL_UI_RELATIVE_LAYOUT_PRIVATE_H
#define EFL_UI_RELATIVE_LAYOUT_PRIVATE_H
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#define EFL_PACK_LAYOUT_PROTECTED
#include <Elementary.h>
#include "elm_priv.h"
typedef enum _Efl_Ui_Relative_Layout_Calc_State
{
RELATIVE_CALC_NONE,
RELATIVE_CALC_DONE,
RELATIVE_CALC_ON
} Efl_Ui_Relative_Layout_Calc_State;
typedef struct _Efl_Ui_Relative_Layout_Data Efl_Ui_Relative_Layout_Data;
typedef struct _Efl_Ui_Relative_Layout_Child Efl_Ui_Relative_Layout_Child;
typedef struct _Efl_Ui_Relative_Layout_Calc Efl_Ui_Relative_Layout_Calc;
typedef struct _Efl_Ui_Relative_Layout_Relation Efl_Ui_Relative_Layout_Relation;
typedef struct _Efl_Ui_Relative_Layout_Content_Iterator Efl_Ui_Relative_Layout_Content_Iterator;
struct _Efl_Ui_Relative_Layout_Calc
{
EINA_INLIST;
int max[2];
int min[2];
int aspect[2];
int margin[4];
Efl_Gfx_Hint_Aspect aspect_type;
Eina_Bool fill[2];
double weight[2];
double align[2];
double comp_factor;
/* m0 is static min size which is added to the other children min size.
* only if both (target, relative)[0] and (target, relative)[1] are same,
* it has non-zero value. it is calculated as (min * (align / relative)) if
* align is greater than relative, (min * ((1 - align) / (1 - relative))) otherwise.
* mi, mj are transformed relative based on layout min size. they are
* calculated as (target.mi + (relative * (target.mj - target.mi))). for example,
* there are two children of relative_layout that has different target base.
* | | obj1 | obj2 |
* | min | 100 | 100 |
* |left.target | layout| obj1 |
* |left.relative | 0.0 | 0.5 |
* |right.target | layout| obj1 |
* |right.relative| 0.5 | 1.0 |
* | mi | 0.0 | 0.25 |
* | mj | 0.5 | 0.5 |
*
* obj1.mi = layout.mi(0.0) + (obj1.relative(0.0) * (layout.mj(1.0) - layout.mi(0.0))) = 0.0
* obj1.mj = layout.mi(0.0) + (obj1.relative(0.5) * (layout.mj(1.0) - layout.mi(0.0))) = 0.5
* obj2.mi = obj1.mi(0.0) + (obj2.relative(0.5) * (obj1.mj(0.5) - obj1.mi(0.0))) = 0.25
* obj2.mj = obj1.mi(0.0) + (obj2.relative(1.0) * (obj1.mj(0.5) - obj1.mi(0.0))) = 0.5
* layout min size is calculated as maximum of (child_min + m0) / (mj - mi).
* in the example, obj1 require layout min size as
* ((child_min(100) + m0(0)) / (mj(0.5) - mi(0.0))) = 200. obj2 require
* layout min size as ((100 + 0) / (0.5 - 0.25)) = 400. as a result, layout
* min size is max(200, 400) = 400.
*/
double m0[2];
double mi[2], mj[2];
struct {
int position;
double length;
} space[2], want[2];
Efl_Ui_Relative_Layout_Calc_State state[2];
Efl_Ui_Relative_Layout_Calc_State chain_state[2];
Efl_Ui_Relative_Layout_Child *to[4];
};
struct _Efl_Ui_Relative_Layout_Data
{
Eo *obj;
Eo *clipper;
Eina_Hash *children;
Efl_Ui_Relative_Layout_Child *base;
};
struct _Efl_Ui_Relative_Layout_Relation
{
Efl_Object *to;
double relative;
};
struct _Efl_Ui_Relative_Layout_Child
{
Eo *obj;
Eo *layout;
Efl_Ui_Relative_Layout_Relation rel[4];
Efl_Ui_Relative_Layout_Calc calc;
};
struct _Efl_Ui_Relative_Layout_Content_Iterator
{
Eina_Iterator iterator;
Eina_Iterator *real_iterator;
Eo *relative_layout;
};
#define EFL_UI_RELATIVE_LAYOUT_RELATION_SET_GET(direction, DIRECTION) \
EOLIAN static void \
_efl_ui_relative_layout_relation_ ## direction ## _set(Eo *obj, Efl_Ui_Relative_Layout_Data *pd, Eo *child, Eo *target, double relative) \
{ \
Efl_Ui_Relative_Layout_Child *rc; \
if (!child) return; \
rc = _relative_child_get(pd, child); \
if (!rc) return; \
if (target) rc->rel[DIRECTION].to = target; \
if (relative < 0) relative = 0; \
else if (relative > 1) relative = 1; \
rc->rel[DIRECTION].relative = relative; \
efl_pack_layout_request(obj); \
} \
\
EOLIAN static void \
_efl_ui_relative_layout_relation_ ## direction ## _get(const Eo *obj EINA_UNUSED, Efl_Ui_Relative_Layout_Data *pd, Eo *child, Eo **target, double *relative) \
{ \
Efl_Ui_Relative_Layout_Child *rc; \
Eo *rel_to = NULL; \
double rel_relative = 0.0; \
rc = eina_hash_find(pd->children, &child); \
if (rc) \
{ \
rel_to = rc->rel[DIRECTION].to; \
rel_relative = rc->rel[DIRECTION].relative; \
} \
else \
ERR("child(%p(%s)) is not registered", child, efl_class_name_get(child)); \
if (target) *target = rel_to; \
if (relative) *relative = rel_relative; \
}
#endif