Aspect support

Try to support AS by calculating items having AS before items without it.
However, we should calculate all items together:
- calculate available slot for each item based on weight
- calculate size for AS items based on AS restriction
- for other items, calculate based on fill also
- calculate align after having available slot and final size
This commit is contained in:
Thiep Ha 2017-08-11 10:55:45 +09:00
parent 746e0f62c4
commit 635af90cb6
3 changed files with 272 additions and 71 deletions

View File

@ -18,6 +18,7 @@ typedef enum {
TWO
} Weight_Mode;
/*
static void
weights_cb(void *data, const Efl_Event *event)
{
@ -210,6 +211,7 @@ custom_check_cb(void *data, const Efl_Event *event)
// function was just overridden.
efl_pack_layout_request(box);
}
*/
void
test_ui_box(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
@ -231,7 +233,7 @@ test_ui_box(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_in
/* controls */
f = elm_frame_add(win);
/*f = elm_frame_add(win);
elm_object_text_set(f, "Controls");
efl_gfx_size_hint_align_set(f, -1, -1);
efl_gfx_size_hint_weight_set(f, 1, 0);
@ -244,7 +246,7 @@ test_ui_box(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_in
efl_gfx_visible_set(hbox, 1);
/* weights radio group */
/* weights radio group *
bx = efl_add(EFL_UI_BOX_CLASS, win,
efl_orientation_set(efl_added, EFL_ORIENT_DOWN));
efl_gfx_size_hint_align_set(bx, 0, -1);
@ -298,7 +300,7 @@ test_ui_box(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_in
elm_radio_value_set(chk, NONE);
/* misc */
/* misc *
bx = efl_add(EFL_UI_BOX_CLASS, win,
efl_orientation_set(efl_added, EFL_ORIENT_DOWN));
efl_gfx_size_hint_align_set(bx, 0, -1);
@ -353,7 +355,7 @@ test_ui_box(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_in
efl_gfx_visible_set(o, 1);
/* user min size setter */
/* user min size setter *
bx = efl_add(EFL_UI_BOX_CLASS, win,
efl_orientation_set(efl_added, EFL_ORIENT_DOWN));
efl_gfx_size_hint_align_set(bx, 0, -1);
@ -380,7 +382,7 @@ test_ui_box(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_in
efl_gfx_visible_set(o, 1);
/* inner box padding */
/* inner box padding *
bx = efl_add(EFL_UI_BOX_CLASS, win,
efl_orientation_set(efl_added, EFL_ORIENT_DOWN));
efl_gfx_size_hint_align_set(bx, 0, -1);
@ -407,7 +409,7 @@ test_ui_box(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_in
efl_gfx_visible_set(o, 1);
/* outer margin */
/* outer margin *
bx = efl_add(EFL_UI_BOX_CLASS, win,
efl_orientation_set(efl_added, EFL_ORIENT_DOWN));
efl_gfx_size_hint_align_set(bx, 0, -1);
@ -434,7 +436,7 @@ test_ui_box(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_in
efl_gfx_visible_set(o, 1);
/* Box align */
/* Box align *
bx = efl_add(EFL_UI_BOX_CLASS, win,
efl_orientation_set(efl_added, EFL_ORIENT_DOWN));
efl_gfx_size_hint_align_set(bx, 0, -1);
@ -472,7 +474,7 @@ test_ui_box(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_in
elm_slider_step_set(o, 0.1);
elm_slider_value_set(o, 0.5);
efl_pack(bx, o);
efl_gfx_visible_set(o, 1);
efl_gfx_visible_set(o, 1);*/
/* contents */
@ -493,13 +495,14 @@ test_ui_box(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_in
objects[i++] = o = elm_button_add(win);
elm_object_text_set(o, "Btn1");
efl_gfx_size_hint_weight_set(o, 1, 1);
efl_pack(bx, o);
efl_gfx_visible_set(o, 1);
objects[i++] = o = elm_button_add(win);
elm_object_text_set(o, "Button 2");
efl_gfx_size_hint_align_set(o, -1, -1);
efl_gfx_size_hint_aspect_set(o, EFL_GFX_SIZE_HINT_ASPECT_BOTH, 2, 1);
efl_gfx_size_hint_aspect_set(o, EFL_GFX_SIZE_HINT_ASPECT_BOTH, 3, 1);
efl_pack(bx, o);
efl_gfx_visible_set(o, 1);

View File

@ -151,7 +151,7 @@ elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
evas_object_box_layout_stack);
elm_box_layout_set(bx, evas_object_box_layout_horizontal, NULL, NULL);
_test_box_transition_change(&tdata);
//_test_box_transition_change(&tdata);
evas_object_resize(win, 300, 320);
evas_object_show(win);

View File

@ -21,6 +21,7 @@ struct _Item_Calc
int id;
};
#define D(format, args...) WRN("item: %d (%s): " format, id, elm_object_text_get((items[id]).obj), ##args)
void
_efl_ui_box_custom_layout(Efl_Ui_Box *ui_box, Evas_Object_Box_Data *bd)
{
@ -41,6 +42,7 @@ _efl_ui_box_custom_layout(Efl_Ui_Box *ui_box, Evas_Object_Box_Data *bd)
evas_object_geometry_get(ui_box, &boxx, &boxy, &boxw, &boxh);
efl_gfx_size_hint_margin_get(ui_box, &boxl, &boxr, &boxt, &boxb);
scale = evas_object_scale_get(ui_box);
WRN("box geo: %d %d %d %d ------------------------------", boxx, boxy, boxw, boxh);
// Box align: used if "item has max size and fill" or "no item has a weight"
// Note: cells always expand on the orthogonal direction
@ -81,7 +83,8 @@ _efl_ui_box_custom_layout(Efl_Ui_Box *ui_box, Evas_Object_Box_Data *bd)
efl_gfx_size_hint_max_get(o, &item->max[0], &item->max[1]);
efl_gfx_size_hint_combined_min_get(o, &item->want[0], &item->want[1]);
efl_gfx_size_hint_aspect_get(o, &item->aspect, &item->aw, &item->ah);
efl_gfx_size_hint_min_get(0, &item->min[0], &item->min[1]);
efl_gfx_size_hint_min_get(o, &item->min[0], &item->min[1]);
D("weight: %1.f %.1f, align: %.1f %.1f, min: %d %d, max: %d %d, aspect: (%d) %d %d", item->weight[0], item->weight[1], item->align[0], item->align[1], item->min[0], item->min[1], item->max[0], item->max[1], item->aspect, item->aw, item->ah);
if (item->aw == 0 || item->ah == 0)
{
item->aw = item->ah = 0;
@ -90,12 +93,74 @@ _efl_ui_box_custom_layout(Efl_Ui_Box *ui_box, Evas_Object_Box_Data *bd)
//aspect ratio support
//lam sao de tinh chi tinh min + van support aspect ratio???
//if (item->aspect == EFL_GFX_SIZE_HINT_ASPECT_HORIZONTAL ||
// item->aspect == EFL_GFX_SIZE_HINT_ASPECT_BOTH)
if (item->aspect >= EFL_GFX_SIZE_HINT_ASPECT_HORIZONTAL)
{
int minh = item->want[0] * item->ah / item->aw;
if (item->want[1] < minh)
item->want[1] = minh;
int w1, h1;
if (horiz)
{
if (item->min[0] > 0)
{
w1 = item->min[0];
h1 = w1 * item->ah / item->aw;
if (h1 < item->min[1])
{
h1 = item->min[1];
w1 = h1 * item->aw / item->ah;
}
D("min: %d %d, w h: %d %d", item->min[0], item->min[1], w1, h1);
}
else if (item->min[1] > 0)
{
h1 = item->min[1];
w1 = h1 * item->aw / item->ah;
if (w1 < item->min[0])
{
w1 = item->min[0];
h1 = w1 * item->ah / item->aw;
}
D("min: %d %d, w h: %d %d", item->min[0], item->min[1], w1, h1);
}
else
{
//no min: keep combined min + aspect
if (item->aw < item->ah)
{
w1 = item->want[0];
h1 = w1 * item->ah / item->aw;
D("want: %d %d, w h: %d %d", item->want[0], item->want[1], w1, h1);
}
else
{
h1 = item->want[1];
w1 = h1 * item->aw / item->ah;
D("want: %d %d, w h: %d %d", item->want[0], item->want[1], w1, h1);
}
}
if (w1 > 0 || h1 > 0)
{
item->want[0] = w1;
item->want[1] = h1;
}
}
else
{
//FIXME: add more handling as horiz case
w1 = item->min[0];
h1 = w1 * item->ah / item->aw;
if (h1 < item->min[1])
{
h1 = item->min[1];
w1 = h1 * item->aw / item->ah;
}
if (w1 > 0 || h1 > 0)
{
item->want[0] = w1;
item->want[1] = h1;
}
}
//int minh = item->want[0] * item->ah / item->aw;
//if (item->want[1] < minh)
// item->want[1] = minh;
}
if (item->weight[0] < 0) item->weight[0] = 0;
@ -132,6 +197,7 @@ _efl_ui_box_custom_layout(Efl_Ui_Box *ui_box, Evas_Object_Box_Data *bd)
wantw = item->want[0];
}
D("want: %d %d :: %d %d", item->want[0], item->want[1], wantw, wanth);
item->id = id++;
}
@ -229,8 +295,130 @@ _efl_ui_box_custom_layout(Efl_Ui_Box *ui_box, Evas_Object_Box_Data *bd)
wanth + pad * (count - 1) + boxt + boxb);
}*/
WRN("total weight: %.1f %.1f, extra: %.1f", weight[0], weight[1], extra);
if (extra < 0) extra = 0;
double cx, cy, cw, ch, x, y, w, h;
//work on items having aspect ratio first
for (id = 0; id < count; id++)
{
item = &items[id];
if (item->aspect >= EFL_GFX_SIZE_HINT_ASPECT_HORIZONTAL)
{
if (horiz)
{
//consider aspect, min, max, fill
int old_w = item->want[0];
int w1 = item->want[0];
int h1 = item->want[1];
if (weight[0] > 0)
w1 = item->want[0] + extra * item->weight[0] / weight[0];
h1 = w1 * item->ah / item->aw;
D("w h: %d %d, want: %d %d, extra: %d, weight: %.1f / %.1f", w1, h1, item->want[0], item->want[1], extra, item->weight[0], weight[0]);
if (h1 < item->want[1])
{
h1 = item->want[1];
w1 = h1 * item->aw / item->ah;
D("w h: %d %d", w1, h1);
}
if (item->aspect == EFL_GFX_SIZE_HINT_ASPECT_BOTH ||
item->aspect == EFL_GFX_SIZE_HINT_ASPECT_VERTICAL)
{
if (h1 > boxh)
{
h1 = boxh;
w1 = h1 * item->aw / item->ah;
}
}
//aspect and fill: aspect does not respect fill
/*if (item->align[1] < 0) //should check in first place
{
h1 = boxh;
w1 = h1 * item->aw / item->ah;
D("w, h: %d %d", w1, h1);
}*/
//aspect and max
double mar = 0.0;
if ((item->max[0] != INT_MAX) && (item->max[1] != INT_MAX))
{
mar = item->max[0] / (double)item->max[1];
D("mar: %.2f, max: %d %d", mar, item->max[0], item->max[1]);
if (item->ah > 0)
{
double ar = item->aw / (double)item->ah;
D("ar: %.2f, mar: %.2f", ar, mar);
if (ar < mar)
{
if (h1 > item->max[1])
{
h1 = item->max[1];
w1 = h1 * item->aw / item->ah;
}
D("w, h: %d %d", w1, h1);
}
else
{
if (w1 > item->max[0])
{
w1 = item->max[0];
h1 = w1 * item->ah / item->aw;
}
D("w, h: %d %d", w1, h1);
}
}
}
item->want[0] = w1;
item->want[1] = h1;
extra -= item->want[0] - old_w;
weight[0] -= item->weight[0];
D("horiz: w, h: %d %d, extra: %d", w1, h1, extra);
/*ch = boxh;
if (ch > item->max[1])
ch = item->max[1];
cw = ch * item->aw / item->ah;
if (cw > item->max[0])
{
cw = item->max[0];
ch = cw * item->ah / item->aw;
}*/
}
else
{
int w1, h1;
int old_h = item->want[1];
h1 = item->want[1] + extra * item->weight[1] / weight[1];
w1 = h1 * item->aw / item->ah;
if (item->aspect == EFL_GFX_SIZE_HINT_ASPECT_BOTH ||
item->aspect == EFL_GFX_SIZE_HINT_ASPECT_HORIZONTAL)
{
if (w1 > boxw)
{
w1 = boxw;
h1 = w1 * item->ah / item->aw;
}
}
D("vertical: w,h: %d %d", w1, h1);
item->want[0] = w1;
item->want[1] = h1;
extra -= item->want[1] - old_h;
weight[1] -= item->weight[1];
/*cw = boxw;
if (cw > item->max[0])
cw = item->max[0];
ch = cw * item->ah / item->aw;
if (ch > item->max[1])
{
ch = item->max[1];
cw = ch * item->aw / item->ah;
}*/
}
}
}
if (EINA_DBL_EQ(weight[!horiz], 0))
{
if (box_fill[!horiz])
@ -246,40 +434,6 @@ _efl_ui_box_custom_layout(Efl_Ui_Box *ui_box, Evas_Object_Box_Data *bd)
weight[!horiz] = count;
}
double cx, cy, cw, ch, x, y, w, h;
//work on items having aspect ratio first
for (id = 0; id < count; id++)
{
item = &items[id];
if (item->aspect)
{
if (horiz)
{
ch = boxh;
if (ch > item->max[1])
ch = item->max[1];
cw = ch * item->aw / item->ah;
if (cw > item->max[0])
{
cw = item->max[0];
ch = cw * item->ah / item->aw;
}
}
else
{
cw = boxw;
if (cw > item->max[0])
cw = item->max[0];
ch = cw * item->ah / item->aw;
if (ch > item->max[1])
{
ch = item->max[1];
cw = ch * item->aw / item->ah;
}
}
}
}
for (id = 0; id < count; id++)
{
double cx, cy, cw, ch, x, y, w, h;
@ -293,55 +447,88 @@ _efl_ui_box_custom_layout(Efl_Ui_Box *ui_box, Evas_Object_Box_Data *bd)
{
cx = boxx + cur_pos;
cy = boxy;
cw = item->want[0] + rounding + (zeroweight ? 1.0 : item->weight[0]) * extra / weight[0];
ch = boxh;
//phan phoi extra cho cac items
if (item->aspect >= EFL_GFX_SIZE_HINT_ASPECT_HORIZONTAL)
{
cw = item->want[0];
ch = item->want[1];
}
else
{
cw = item->want[0] + rounding + (zeroweight ? 1.0 : item->weight[0]) * extra / weight[0];
ch = boxh;
}
cur_pos += cw + pad;
}
else
{
cx = boxx;
cy = boxy + cur_pos;
cw = boxw;
ch = item->want[1] + rounding + (zeroweight ? 1.0 : item->weight[1]) * extra / weight[1];
if (item->aspect >= EFL_GFX_SIZE_HINT_ASPECT_HORIZONTAL)
{
cw = item->want[0];
ch = item->want[1];
}
else
{
cw = boxw;
ch = item->want[1] + rounding + (zeroweight ? 1.0 : item->weight[1]) * extra / weight[1];
}
cur_pos += ch + pad;
}
// horizontally
if (item->max[0] < INT_MAX)
{
w = MIN(MAX(item->want[0] - item->pad[0] - item->pad[1], item->max[0]), cw);
if (item->aspect < EFL_GFX_SIZE_HINT_ASPECT_HORIZONTAL)
w = MIN(MAX(item->want[0] - item->pad[0] - item->pad[1], item->max[0]), cw);
else
w = item->want[0];
if (item->align[0] < 0)
{
// bad case: fill+max are not good together
x = cx + ((cw - w) * box_align[0]) + item->pad[0];
}
else
x = cx + ((cw - w) * item->align[0]) + item->pad[0];
{
x = cx + ((cw - w) * item->align[0]) + item->pad[0];
D("x: %.1f, cx: %.1f", x, cx);
}
}
else if (item->align[0] < 0)
{
// fill x
w = cw - item->pad[0] - item->pad[1];
if (item->aspect < EFL_GFX_SIZE_HINT_ASPECT_HORIZONTAL)
w = cw - item->pad[0] - item->pad[1];
else
w = item->want[0];
x = cx + item->pad[0];
D("x: %.1f, cx: %.1f", x, cx);
}
else
{
w = item->want[0] - item->pad[0] - item->pad[1];
//lam sao support align + weight???
//w = item->want[0] - item->pad[0] - item->pad[1];
w = cw - item->pad[0] - item->pad[1];
x = cx + ((cw - w) * item->align[0]) + item->pad[0];
D("x: %.1f, cx: %.1f", x, cx);
}
//aspect ratio
if (item->aspect)
/*if (item->aspect)
{
h = w * item->ah / item->aw;
if (h > wanth)
wanth = h;
}
h = w * item->ah / item->aw;
if (h > wanth)
wanth = h;
}*/
/////
// vertically
if (item->max[1] < INT_MAX)
{
h = MIN(MAX(item->want[1] - item->pad[2] - item->pad[3], item->max[1]), ch);
if (item->aspect < EFL_GFX_SIZE_HINT_ASPECT_HORIZONTAL)
h = MIN(MAX(item->want[1] - item->pad[2] - item->pad[3], item->max[1]), ch);
else
h = item->want[1];
if (item->align[1] < 0)
{
// bad case: fill+max are not good together
@ -353,7 +540,10 @@ _efl_ui_box_custom_layout(Efl_Ui_Box *ui_box, Evas_Object_Box_Data *bd)
else if (item->align[1] < 0)
{
// fill y
h = ch - item->pad[2] - item->pad[3];
if (item->aspect < EFL_GFX_SIZE_HINT_ASPECT_HORIZONTAL)
h = ch - item->pad[2] - item->pad[3];
else
h = item->want[1];
y = cy + item->pad[2];
}
else
@ -361,29 +551,37 @@ _efl_ui_box_custom_layout(Efl_Ui_Box *ui_box, Evas_Object_Box_Data *bd)
h = item->want[1] - item->pad[2] - item->pad[3];
y = cy + ((ch - h) * item->align[1]) + item->pad[2];
}
if (item->aspect)
/*if (item->aspect)
{
w = h * item->aw / item->ah;
cur_pos = cur_pos - cw + w;
if (w > wantw)
wantw = w;
}
w = h * item->aw / item->ah;
cur_pos = cur_pos - cw + w;
//if (w > wantw)
// wantw = w;
wantw += w;
}*/
//DBG("[%2d/%2d] cell: %.0f,%.0f %.0fx%.0f item: %.0f,%.0f %.0fx%.0f",
// id, count, cx, cy, cw, ch, x, y, w, h);
D("geo: %.0f %.0f %.0f %.0f", x, y, w, h);
evas_object_geometry_set(item->obj, x, y, w, h);
}
int hh, hw;
if (horiz)
{
evas_object_size_hint_min_set(ui_box,
wantw + boxl + boxr + pad * (count - 1),
wanth + boxt + boxb);
hw = wantw + boxl + boxr + pad * (count - 1);
hh = wanth + boxt + boxb;
}
else
{
evas_object_size_hint_min_set(ui_box,
wantw + boxl + boxr,
wanth + pad * (count - 1) + boxt + boxb);
hw = wantw + boxl + boxr;
hh = wanth + pad * (count - 1) + boxt + boxb;
}
WRN("box min: %d %d", hw, hh);
}