summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYeongjong Lee <yj34.lee@samsung.com>2019-05-29 17:24:21 +0900
committerJaehyun Cho <jae_hyun.cho@samsung.com>2019-05-29 17:24:21 +0900
commite3a791c4b176b7c396b1f4c56cd7a1ad54f1b745 (patch)
tree6cc45b067dc45dc404204ff50acbcf2177e4131f
parent8721caf787ce1a9abb6198f41bfc1a033d4f799a (diff)
downloadefl-e3a791c4b176b7c396b1f4c56cd7a1ad54f1b745.tar.gz
efl_ui_relative_layout: allow to respect the min size of its child
Summary: It will have the same policy as the Efl.Ui.Box, Table. Test Plan: elementary_test -to 'efl.ui.relative_layout' Reviewers: Jaehyun_Cho, herb Reviewed By: Jaehyun_Cho Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9029
-rw-r--r--src/lib/elementary/efl_ui_relative_layout.c78
-rw-r--r--src/lib/elementary/efl_ui_relative_layout_private.h28
2 files changed, 100 insertions, 6 deletions
diff --git a/src/lib/elementary/efl_ui_relative_layout.c b/src/lib/elementary/efl_ui_relative_layout.c
index 530179cab4..a0814cebad 100644
--- a/src/lib/elementary/efl_ui_relative_layout.c
+++ b/src/lib/elementary/efl_ui_relative_layout.c
@@ -177,6 +177,11 @@ _child_aspect_calc(Efl_Ui_Relative_Layout_Child *child, Eina_Bool axis)
calc->want[0].length = calc->want[1].length * calc->aspect[0] / calc->aspect[1];
}
//calculate min size
+ if (calc->aspect[1] > calc->aspect[0])
+ calc->min[1] = calc->min[0] * calc->aspect[1] / calc->aspect[0];
+ else
+ calc->min[0] = calc->min[1] * calc->aspect[0] / calc->aspect[1];
+
if (calc->want[0].length < calc->min[0])
{
calc->want[0].length = calc->min[0];
@@ -298,8 +303,17 @@ _child_chain_calc(Efl_Ui_Relative_Layout_Child *child, Eina_Bool axis)
cur_pos += o->calc.space[axis].length;
o->calc.space[axis].length -= o->calc.margin[START] + o->calc.margin[END];
o->calc.chain_state[axis] = RELATIVE_CALC_DONE;
+ child->calc.m0[axis] += o->calc.min[axis];
}
+ child->calc.mi[axis] = head->rel[START].relative * (head->calc.to[START]->calc.mj[axis] -
+ head->calc.to[START]->calc.mi[axis]) + head->calc.to[START]->calc.mi[axis];
+ child->calc.mj[axis] = tail->rel[END].relative * (tail->calc.to[END]->calc.mj[axis] -
+ tail->calc.to[END]->calc.mi[axis]) + tail->calc.to[END]->calc.mi[axis];
+ child->calc.m0[axis] += -child->calc.min[axis] +
+ (head->calc.to[START]->calc.m0[axis] * head->rel[START].relative) +
+ (tail->calc.to[END]->calc.m0[axis] * (1 - tail->rel[END].relative));
+
return EINA_TRUE;
}
@@ -355,6 +369,32 @@ _child_calc(Efl_Ui_Relative_Layout_Child *child, Eina_Bool axis)
(calc->space[axis].length - calc->want[axis].length) * calc->align[axis];
child->calc.state[axis] = RELATIVE_CALC_DONE;
+ if (child->calc.chain_state[axis] == RELATIVE_CALC_DONE)
+ return;
+
+ //calculate relative layout min
+ calc->mi[axis] = child->rel[START].relative * (calc->to[START]->calc.mj[axis] -
+ calc->to[START]->calc.mi[axis]) + calc->to[START]->calc.mi[axis];
+ calc->mj[axis] = child->rel[END].relative * (calc->to[END]->calc.mj[axis] -
+ calc->to[END]->calc.mi[axis]) + calc->to[END]->calc.mi[axis];
+ calc->m0[axis] = calc->to[START]->calc.m0[axis] * child->rel[START].relative;
+
+ if ((calc->to[START] == calc->to[END]) &&
+ EINA_DBL_EQ(child->rel[START].relative, child->rel[END].relative))
+ {
+ double r, a; // relative, align
+ r = calc->mi[axis] +
+ (child->rel[START].relative * (calc->mj[axis] - calc->mi[axis]));
+ a = calc->align[axis];
+ calc->m0[axis] += (calc->min[axis] + calc->margin[START] + calc->margin[END]) *
+ ((EINA_DBL_EQ(r, 0.0) || (!EINA_DBL_EQ(r, 1.0) && (a < r))) ?
+ ((1 - a) / (1 - r)) : (a / r));
+ }
+ else
+ {
+ calc->m0[axis] += calc->to[END]->calc.m0[axis] * (1 - child->rel[END].relative);
+ }
+
}
static void
@@ -386,18 +426,36 @@ _hash_clear_cb(void *data)
static Eina_Bool
_hash_child_calc_foreach_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
- void *data, void *fdata EINA_UNUSED)
+ void *data, void *fdata)
{
Efl_Ui_Relative_Layout_Child *child = data;
+ Efl_Ui_Relative_Layout_Calc *calc = &(child->calc);
+ Efl_Ui_Relative_Layout_Data *pd = fdata;
Eina_Rect want;
+ int axis, layout_min;
+ double min_len;
_child_calc(child, 0);
_child_calc(child, 1);
- want.x = child->calc.want[0].position;
- want.w = child->calc.want[0].length;
- want.y = child->calc.want[1].position;
- want.h = child->calc.want[1].length;
+ want.x = calc->want[0].position;
+ want.w = calc->want[0].length;
+ want.y = calc->want[1].position;
+ want.h = calc->want[1].length;
+
+ for (axis = 0; axis < 2; axis++)
+ {
+ layout_min = 0;
+ min_len = calc->mj[axis] - calc->mi[axis];
+ if (EINA_DBL_EQ(min_len, 0.0))
+ layout_min = calc->m0[axis];
+ else
+ layout_min = ((calc->min[axis] + calc->margin[START] +
+ calc->margin[END] + calc->m0[axis]) / fabs(min_len)) + 0.5;
+
+ if (pd->base->calc.min[axis] < layout_min)
+ pd->base->calc.min[axis] = layout_min;
+ }
efl_gfx_entity_geometry_set(child->obj, want);
return EINA_TRUE;
@@ -437,6 +495,8 @@ _hash_child_init_foreach_cb(const Eina_Hash *hash EINA_UNUSED, const void *key E
calc->max[1] = max.h;
calc->min[0] = min.w;
calc->min[1] = min.h;
+ calc->m0[0] = 0.0;
+ calc->m0[1] = 0.0;
calc->want[0].position = 0;
calc->want[0].length = 0;
@@ -477,9 +537,13 @@ _efl_ui_relative_layout_efl_pack_layout_layout_update(Eo *obj, Efl_Ui_Relative_L
pd->base->calc.want[0].length = want.w;
pd->base->calc.want[1].position = want.y;
pd->base->calc.want[1].length = want.h;
+ pd->base->calc.min[0] = 0;
+ pd->base->calc.min[1] = 0;
eina_hash_foreach(pd->children, _hash_child_init_foreach_cb, pd);
- eina_hash_foreach(pd->children, _hash_child_calc_foreach_cb, NULL);
+ eina_hash_foreach(pd->children, _hash_child_calc_foreach_cb, pd);
+
+ efl_gfx_hint_size_restricted_min_set(obj, EINA_SIZE2D(pd->base->calc.min[0], pd->base->calc.min[1]));
efl_event_callback_call(obj, EFL_PACK_EVENT_LAYOUT_UPDATED, NULL);
}
@@ -550,6 +614,8 @@ _efl_ui_relative_layout_efl_object_constructor(Eo *obj, Efl_Ui_Relative_Layout_D
pd->base->rel[TOP].relative = 0.0;
pd->base->rel[BOTTOM].to = obj;
pd->base->rel[BOTTOM].relative = 1.0;
+ pd->base->calc.mi[0] = pd->base->calc.mi[1] = 0.0;
+ pd->base->calc.mj[0] = pd->base->calc.mj[1] = 1.0;
pd->base->calc.state[0] = RELATIVE_CALC_DONE;
pd->base->calc.state[1] = RELATIVE_CALC_DONE;
pd->base->calc.chain_state[0] = RELATIVE_CALC_DONE;
diff --git a/src/lib/elementary/efl_ui_relative_layout_private.h b/src/lib/elementary/efl_ui_relative_layout_private.h
index 2aa150a333..79a22bed1d 100644
--- a/src/lib/elementary/efl_ui_relative_layout_private.h
+++ b/src/lib/elementary/efl_ui_relative_layout_private.h
@@ -36,6 +36,34 @@ struct _Efl_Ui_Relative_Layout_Calc
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;