[ui, layout] layout constraint solving, first draft
This commit is contained in:
parent
a569454df5
commit
56874c99d6
|
@ -78,6 +78,7 @@ void debug_print_size(ui_box* box, ui_axis axis, int indent)
|
||||||
{
|
{
|
||||||
debug_print_indent(indent);
|
debug_print_indent(indent);
|
||||||
printf("size %s: ", axis == UI_AXIS_X ? "x" : "y");
|
printf("size %s: ", axis == UI_AXIS_X ? "x" : "y");
|
||||||
|
f32 value = box->targetStyle->size.c[axis].value;
|
||||||
switch(box->targetStyle->size.c[axis].kind)
|
switch(box->targetStyle->size.c[axis].kind)
|
||||||
{
|
{
|
||||||
case UI_SIZE_TEXT:
|
case UI_SIZE_TEXT:
|
||||||
|
@ -89,11 +90,15 @@ void debug_print_size(ui_box* box, ui_axis axis, int indent)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UI_SIZE_PARENT:
|
case UI_SIZE_PARENT:
|
||||||
printf("parent\n");
|
printf("parent: %f\n", value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SIZE_PARENT_MINUS_PIXELS:
|
||||||
|
printf("parent minus pixels: %f\n", value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UI_SIZE_PIXELS:
|
case UI_SIZE_PIXELS:
|
||||||
printf("pixels\n");
|
printf("pixels: %f\n", value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +238,10 @@ void panel_end(void)
|
||||||
ui_box* scrollBarX = 0;
|
ui_box* scrollBarX = 0;
|
||||||
ui_box* scrollBarY = 0;
|
ui_box* scrollBarY = 0;
|
||||||
|
|
||||||
if(contentsW > panel->rect.w)
|
bool needsScrollX = contentsW > panel->rect.w;
|
||||||
|
bool needsScrollY = contentsH > panel->rect.h;
|
||||||
|
|
||||||
|
if(needsScrollX)
|
||||||
{
|
{
|
||||||
f32 thumbRatioX = panel->rect.w / contentsW;
|
f32 thumbRatioX = panel->rect.w / contentsW;
|
||||||
f32 sliderX = panel->scroll.x /(contentsW - panel->rect.w);
|
f32 sliderX = panel->scroll.x /(contentsW - panel->rect.w);
|
||||||
|
@ -242,8 +250,9 @@ void panel_end(void)
|
||||||
.size.height = {UI_SIZE_PIXELS, 10, 0},
|
.size.height = {UI_SIZE_PIXELS, 10, 0},
|
||||||
.floating.x = true,
|
.floating.x = true,
|
||||||
.floating.y = true,
|
.floating.y = true,
|
||||||
.floatTarget = {0, panel->rect.h - 12}},
|
.floatTarget = {0, panel->rect.h - 10}},
|
||||||
UI_STYLE_SIZE);
|
UI_STYLE_SIZE
|
||||||
|
|UI_STYLE_FLOAT);
|
||||||
|
|
||||||
scrollBarX = ui_slider("scrollerX", thumbRatioX, &sliderX);
|
scrollBarX = ui_slider("scrollerX", thumbRatioX, &sliderX);
|
||||||
|
|
||||||
|
@ -255,16 +264,18 @@ void panel_end(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(contentsH > panel->rect.h)
|
if(needsScrollY)
|
||||||
{
|
{
|
||||||
f32 thumbRatioY = panel->rect.h / contentsH;
|
f32 thumbRatioY = panel->rect.h / contentsH;
|
||||||
f32 sliderY = panel->scroll.y /(contentsH - panel->rect.h);
|
f32 sliderY = panel->scroll.y /(contentsH - panel->rect.h);
|
||||||
|
|
||||||
|
f32 spacerSize = needsScrollX ? 10 : 0;
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 10, 0},
|
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 10, 0},
|
||||||
.size.height = {UI_SIZE_PARENT, 1., 0},
|
.size.height = {UI_SIZE_PARENT_MINUS_PIXELS, spacerSize, 0},
|
||||||
.floating.x = true,
|
.floating.x = true,
|
||||||
.floating.y = true,
|
.floating.y = true,
|
||||||
.floatTarget = {panel->rect.w - 12, 0}},
|
.floatTarget = {panel->rect.w - 10, 0}},
|
||||||
UI_STYLE_SIZE
|
UI_STYLE_SIZE
|
||||||
|UI_STYLE_FLOAT);
|
|UI_STYLE_FLOAT);
|
||||||
|
|
||||||
|
@ -277,22 +288,9 @@ void panel_end(void)
|
||||||
ui_box_activate(scrollBarY);
|
ui_box_activate(scrollBarY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panel->scroll.x = Clamp(panel->scroll.x, 0, contentsW - panel->rect.w);
|
panel->scroll.x = Clamp(panel->scroll.x, 0, contentsW - panel->rect.w);
|
||||||
panel->scroll.y = Clamp(panel->scroll.y, 0, contentsH - panel->rect.h);
|
panel->scroll.y = Clamp(panel->scroll.y, 0, contentsH - panel->rect.h);
|
||||||
|
|
||||||
if(scrollBarX)
|
|
||||||
{
|
|
||||||
// ui_box_set_floating(scrollBarX, UI_AXIS_X, panel->scroll.x);
|
|
||||||
// ui_box_set_floating(scrollBarX, UI_AXIS_Y, panel->scroll.y + panel->rect.h - 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(scrollBarY)
|
|
||||||
{
|
|
||||||
// ui_box_set_floating(scrollBarY, UI_AXIS_X, panel->scroll.x + panel->rect.w - 12);
|
|
||||||
// ui_box_set_floating(scrollBarY, UI_AXIS_Y, panel->scroll.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui_box_end();
|
ui_box_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,15 +414,17 @@ int main()
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||||
.size.height = {UI_SIZE_PIXELS, 500}},
|
.size.height = {UI_SIZE_PARENT, 1, 1}},
|
||||||
UI_STYLE_SIZE);
|
UI_STYLE_SIZE);
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X}, UI_STYLE_LAYOUT_AXIS);
|
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X}, UI_STYLE_LAYOUT_AXIS);
|
||||||
ui_container("contents", debugFlags)
|
ui_container("contents", debugFlags)
|
||||||
{
|
{
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5},
|
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5},
|
||||||
.size.height = {UI_SIZE_PARENT, 1}},
|
.size.height = {UI_SIZE_PARENT, 1},
|
||||||
UI_STYLE_SIZE);
|
.borderColor = {0, 0, 1, 1}},
|
||||||
|
UI_STYLE_SIZE
|
||||||
|
|UI_STYLE_BORDER_COLOR);
|
||||||
|
|
||||||
ui_container("left", debugFlags)
|
ui_container("left", debugFlags)
|
||||||
{
|
{
|
||||||
|
@ -519,13 +519,14 @@ int main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5},
|
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5},
|
||||||
.size.height = {UI_SIZE_PARENT, 1}},
|
.size.height = {UI_SIZE_PARENT, 1}},
|
||||||
UI_STYLE_SIZE);
|
UI_STYLE_SIZE);
|
||||||
|
|
||||||
ui_container("right", debugFlags)
|
ui_container("right", debugFlags)
|
||||||
{
|
{
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||||
.size.height = {UI_SIZE_PARENT, 0.33}},
|
.size.height = {UI_SIZE_PARENT, 0.33}},
|
||||||
UI_STYLE_SIZE);
|
UI_STYLE_SIZE);
|
||||||
|
@ -555,136 +556,46 @@ int main()
|
||||||
widget_view("Color")
|
widget_view("Color")
|
||||||
{
|
{
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||||
.size.height = {UI_SIZE_PARENT, 0.7}},
|
.size.height = {UI_SIZE_PARENT, 0.7},
|
||||||
UI_STYLE_SIZE);
|
.layout.axis = UI_AXIS_X},
|
||||||
|
UI_STYLE_SIZE
|
||||||
|
|UI_STYLE_LAYOUT_AXIS);
|
||||||
|
|
||||||
panel("Panel", UI_FLAG_DRAW_BORDER)
|
panel("Panel", UI_FLAG_DRAW_BORDER)
|
||||||
{
|
{
|
||||||
|
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X},
|
||||||
|
UI_STYLE_LAYOUT_AXIS);
|
||||||
|
ui_container("contents", 0)
|
||||||
|
{
|
||||||
|
ui_style_next(&(ui_style){.layout.spacing = 20},
|
||||||
|
UI_STYLE_LAYOUT_SPACING);
|
||||||
|
ui_container("buttons", 0)
|
||||||
|
{
|
||||||
|
ui_button("Button A");
|
||||||
|
ui_button("Button B");
|
||||||
|
ui_button("Button C");
|
||||||
|
ui_button("Button D");
|
||||||
|
}
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.layout.spacing = 20},
|
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X,
|
||||||
UI_STYLE_LAYOUT_SPACING);
|
.layout.spacing = 20},
|
||||||
ui_container("buttons", 0)
|
UI_STYLE_LAYOUT_SPACING
|
||||||
{
|
|UI_STYLE_LAYOUT_AXIS);
|
||||||
ui_button("Button A");
|
|
||||||
ui_button("Button B");
|
ui_container("buttons2", 0)
|
||||||
ui_button("Button C");
|
{
|
||||||
ui_button("Button D");
|
ui_button("Button A");
|
||||||
|
ui_button("Button B");
|
||||||
|
ui_button("Button C");
|
||||||
|
ui_button("Button D");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/*
|
|
||||||
ui_pattern pattern = {0};
|
|
||||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = STR8("b")});
|
|
||||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TAG, .tag = ui_tag_make("foo")});
|
|
||||||
ui_style_match_before(pattern, &(ui_style){.fontSize = 36}, UI_STYLE_FONT_SIZE);
|
|
||||||
|
|
||||||
ui_style_match_before(ui_pattern_all(),
|
|
||||||
&defaultStyle,
|
|
||||||
UI_STYLE_FONT
|
|
||||||
|UI_STYLE_FONT_SIZE
|
|
||||||
|UI_STYLE_COLOR
|
|
||||||
|UI_STYLE_BORDER_SIZE
|
|
||||||
|UI_STYLE_BORDER_COLOR
|
|
||||||
|UI_STYLE_SIZE_WIDTH
|
|
||||||
|UI_STYLE_SIZE_HEIGHT
|
|
||||||
|UI_STYLE_LAYOUT);
|
|
||||||
|
|
||||||
|
|
||||||
pattern = (ui_pattern){0};
|
|
||||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = STR8("c")});
|
|
||||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TAG, .tag = ui_tag_make("button")});
|
|
||||||
ui_style_match_after(pattern,
|
|
||||||
&(ui_style){.bgColor = {1, 0.5, 0.5, 1}},
|
|
||||||
UI_STYLE_BG_COLOR);
|
|
||||||
|
|
||||||
pattern = (ui_pattern){0};
|
|
||||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = STR8("c")});
|
|
||||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TAG, .tag = ui_tag_make("button")});
|
|
||||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_STATUS, .op = UI_SEL_AND, .status = UI_ACTIVE|UI_HOVER});
|
|
||||||
ui_style_match_after(pattern,
|
|
||||||
&(ui_style){.bgColor = {0.5, 1, 0.5, 1}},
|
|
||||||
UI_STYLE_BG_COLOR);
|
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.bgColor = {0.7, 0.7, 0.7, 1}}, UI_STYLE_BG_COLOR);
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, .size.height = {UI_SIZE_PARENT, 1}}, UI_STYLE_SIZE);
|
|
||||||
|
|
||||||
ui_container("a", defaultFlags)
|
|
||||||
{
|
|
||||||
ui_pattern pattern = {0};
|
|
||||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = STR8("b")});
|
|
||||||
ui_style_match_before(pattern, &(ui_style){.fontSize = 22}, UI_STYLE_FONT_SIZE);
|
|
||||||
|
|
||||||
ui_container("b", defaultFlags)
|
|
||||||
{
|
|
||||||
ui_container("c", defaultFlags)
|
|
||||||
{
|
|
||||||
if(ui_button("button d").clicked)
|
|
||||||
{
|
|
||||||
printf("clicked button d\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ui_container("e", defaultFlags)
|
|
||||||
{
|
|
||||||
ui_tag_next("foo");
|
|
||||||
if(ui_button("button f").clicked)
|
|
||||||
{
|
|
||||||
printf("clicked button f\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
|
||||||
.size.height = {UI_SIZE_PIXELS, 20, 0}},
|
|
||||||
UI_STYLE_SIZE);
|
|
||||||
static f32 slider1 = 0;
|
|
||||||
ui_slider("slider1", 0.3, &slider1);
|
|
||||||
|
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
|
||||||
.size.height = {UI_SIZE_PIXELS, 20, 0}},
|
|
||||||
UI_STYLE_SIZE);
|
|
||||||
static f32 slider2 = 0;
|
|
||||||
ui_slider("slider2", 0.3, &slider2);
|
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
|
||||||
.size.height = {UI_SIZE_PIXELS, 20}},
|
|
||||||
UI_STYLE_SIZE);
|
|
||||||
static f32 slider3 = 0;
|
|
||||||
ui_slider("slider3", 0.3, &slider3);
|
|
||||||
|
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 20},
|
|
||||||
.size.height = {UI_SIZE_PIXELS, 200}},
|
|
||||||
UI_STYLE_SIZE);
|
|
||||||
static f32 slider4 = 0;
|
|
||||||
ui_slider("slider4", 0.3, &slider4);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X}, UI_STYLE_LAYOUT_AXIS);
|
|
||||||
ui_container("f", defaultFlags)
|
|
||||||
{
|
|
||||||
ui_tag_next("foo");
|
|
||||||
ui_label("label d");
|
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 300},
|
|
||||||
.size.height = {UI_SIZE_TEXT}},
|
|
||||||
UI_STYLE_SIZE);
|
|
||||||
static str8 text = {};
|
|
||||||
ui_text_box_result res = ui_text_box("textbox", mem_scratch(), text);
|
|
||||||
if(res.changed)
|
|
||||||
{
|
|
||||||
mem_arena_clear(&textArena);
|
|
||||||
text = str8_push_copy(&textArena, res.text);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
if(printDebugStyle)
|
if(printDebugStyle)
|
||||||
{
|
{
|
||||||
|
@ -693,32 +604,8 @@ int main()
|
||||||
|
|
||||||
mg_surface_prepare(surface);
|
mg_surface_prepare(surface);
|
||||||
|
|
||||||
// mg_set_color_rgba(1, 0, 0, 1);
|
|
||||||
// mg_rectangle_fill(100, 100, 400, 200);
|
|
||||||
|
|
||||||
ui_draw();
|
ui_draw();
|
||||||
|
|
||||||
/*
|
|
||||||
mg_mat2x3 transform = {1, 0, 0,
|
|
||||||
0, -1, 800};
|
|
||||||
|
|
||||||
bool oldTextFlip = mg_get_text_flip();
|
|
||||||
mg_set_text_flip(true);
|
|
||||||
|
|
||||||
mg_matrix_push(transform);
|
|
||||||
|
|
||||||
mg_set_font(font);
|
|
||||||
mg_set_font_size(20);
|
|
||||||
mg_set_color_rgba(0, 0, 0, 1);
|
|
||||||
|
|
||||||
mg_move_to(0, 38);
|
|
||||||
mg_text_outlines(STR8("hello, world"));
|
|
||||||
mg_fill();
|
|
||||||
|
|
||||||
mg_matrix_pop();
|
|
||||||
|
|
||||||
mg_set_text_flip(oldTextFlip);
|
|
||||||
*/
|
|
||||||
mg_flush();
|
mg_flush();
|
||||||
mg_surface_present(surface);
|
mg_surface_present(surface);
|
||||||
|
|
||||||
|
|
|
@ -890,7 +890,7 @@ static void mp_process_mouse_button(NSEvent* nsEvent, mp_window_data* window, mp
|
||||||
double factor = [nsEvent hasPreciseScrollingDeltas] ? 0.1 : 1.0;
|
double factor = [nsEvent hasPreciseScrollingDeltas] ? 0.1 : 1.0;
|
||||||
event.move.x = 0;
|
event.move.x = 0;
|
||||||
event.move.y = 0;
|
event.move.y = 0;
|
||||||
event.move.deltaX = [nsEvent scrollingDeltaX]*factor;
|
event.move.deltaX = -[nsEvent scrollingDeltaX]*factor;
|
||||||
event.move.deltaY = -[nsEvent scrollingDeltaY]*factor;
|
event.move.deltaY = -[nsEvent scrollingDeltaY]*factor;
|
||||||
event.move.mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
event.move.mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
||||||
|
|
||||||
|
|
108
src/ui.c
108
src/ui.c
|
@ -18,10 +18,10 @@ static ui_style UI_STYLE_DEFAULTS =
|
||||||
{
|
{
|
||||||
.size.width = {.kind = UI_SIZE_CHILDREN,
|
.size.width = {.kind = UI_SIZE_CHILDREN,
|
||||||
.value = 0,
|
.value = 0,
|
||||||
.strictness = 0},
|
.relax = 0},
|
||||||
.size.height = {.kind = UI_SIZE_CHILDREN,
|
.size.height = {.kind = UI_SIZE_CHILDREN,
|
||||||
.value = 0,
|
.value = 0,
|
||||||
.strictness = 0},
|
.relax = 0},
|
||||||
|
|
||||||
.layout = {.axis = UI_AXIS_Y,
|
.layout = {.axis = UI_AXIS_Y,
|
||||||
.align = {UI_ALIGN_START,
|
.align = {UI_ALIGN_START,
|
||||||
|
@ -622,7 +622,7 @@ void ui_animate_ui_size(ui_context* ui, ui_size* size, ui_size target, f32 anima
|
||||||
{
|
{
|
||||||
size->kind = target.kind;
|
size->kind = target.kind;
|
||||||
ui_animate_f32(ui, &size->value, target.value, animationTime);
|
ui_animate_f32(ui, &size->value, target.value, animationTime);
|
||||||
ui_animate_f32(ui, &size->strictness, target.strictness, animationTime);
|
ui_animate_f32(ui, &size->relax, target.relax, animationTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_box_compute_styling(ui_context* ui, ui_box* box)
|
void ui_box_compute_styling(ui_context* ui, ui_box* box)
|
||||||
|
@ -1037,6 +1037,7 @@ void ui_layout_upward_dependent_size(ui_context* ui, ui_box* box, int axis)
|
||||||
|
|
||||||
ui_size* size = &box->style.size.c[axis];
|
ui_size* size = &box->style.size.c[axis];
|
||||||
|
|
||||||
|
|
||||||
if(size->kind == UI_SIZE_PARENT)
|
if(size->kind == UI_SIZE_PARENT)
|
||||||
{
|
{
|
||||||
ui_box* parent = box->parent;
|
ui_box* parent = box->parent;
|
||||||
|
@ -1045,7 +1046,15 @@ void ui_layout_upward_dependent_size(ui_context* ui, ui_box* box, int axis)
|
||||||
f32 margin = parent->style.layout.margin.c[axis];
|
f32 margin = parent->style.layout.margin.c[axis];
|
||||||
box->rect.c[2+axis] = maximum(0, parent->rect.c[2+axis] - parent->spacing[axis] - 2*margin) * size->value;
|
box->rect.c[2+axis] = maximum(0, parent->rect.c[2+axis] - parent->spacing[axis] - 2*margin) * size->value;
|
||||||
}
|
}
|
||||||
//TODO else?
|
}
|
||||||
|
else if(size->kind == UI_SIZE_PARENT_MINUS_PIXELS)
|
||||||
|
{
|
||||||
|
ui_box* parent = box->parent;
|
||||||
|
if(parent)
|
||||||
|
{
|
||||||
|
f32 margin = parent->style.layout.margin.c[axis];
|
||||||
|
box->rect.c[2+axis] = maximum(0, parent->rect.c[2+axis] - parent->spacing[axis] - 2*margin - size->value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for_list(&box->children, child, ui_box, listElt)
|
for_list(&box->children, child, ui_box, listElt)
|
||||||
|
@ -1055,8 +1064,95 @@ void ui_layout_upward_dependent_size(ui_context* ui, ui_box* box, int axis)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_layout_solve_conflicts(ui_context* ui, ui_box* box, int axis)
|
void ui_layout_solve_conflicts(ui_context* ui, ui_box* box, int axis)
|
||||||
{
|
{/*
|
||||||
//TODO
|
f32 totalContents = box->childrenSum[axis]
|
||||||
|
+ box->spacing[axis]
|
||||||
|
+ 2*box->style.layout.margin.c[axis];
|
||||||
|
*/
|
||||||
|
f32 sum = 0;
|
||||||
|
|
||||||
|
if(box->style.layout.axis == axis)
|
||||||
|
{
|
||||||
|
//NOTE: if we're solving in the layout axis, first recompute the total size
|
||||||
|
// and total slack of children.
|
||||||
|
|
||||||
|
//NOTE: we also recompute children that depend on the parent. Maybe we could combine with upward dependent stuff...
|
||||||
|
f32 margin = box->style.layout.margin.c[axis];
|
||||||
|
f32 parentAvailableSize = maximum(0, box->rect.c[2+axis] - box->spacing[axis] - 2*margin);
|
||||||
|
f32 slack = 0;
|
||||||
|
|
||||||
|
for_list(&box->children, child, ui_box, listElt)
|
||||||
|
{
|
||||||
|
ui_size* size = &child->style.size.c[axis];
|
||||||
|
if(size->kind == UI_SIZE_PARENT)
|
||||||
|
{
|
||||||
|
child->rect.c[2+axis] = parentAvailableSize * size->value;
|
||||||
|
}
|
||||||
|
else if(size->kind == UI_SIZE_PARENT_MINUS_PIXELS)
|
||||||
|
{
|
||||||
|
child->rect.c[2+axis] = maximum(0, parentAvailableSize - size->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ui_box_hidden(child) && !child->style.floating.c[axis])
|
||||||
|
{
|
||||||
|
sum += child->rect.c[2+axis];
|
||||||
|
slack += child->rect.c[2+axis] * child->style.size.c[axis].relax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 totalContents = sum + box->spacing[axis] + 2*box->style.layout.margin.c[axis];
|
||||||
|
f32 excess = ClampLowBound(totalContents - box->rect.c[2+axis], 0);
|
||||||
|
f32 alpha = Clamp(excess / slack, 0, 1);
|
||||||
|
|
||||||
|
//NOTE: then remove excess proportionally to each box slack, and recompute children sum.
|
||||||
|
sum = 0;
|
||||||
|
for_list(&box->children, child, ui_box, listElt)
|
||||||
|
{
|
||||||
|
f32 relax = child->style.size.c[axis].relax;
|
||||||
|
child->rect.c[2+axis] -= alpha * child->rect.c[2+axis] * relax;
|
||||||
|
sum += child->rect.c[2+axis];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//NOTE: if we're solving on the secondary axis, we remove excess to each box individually
|
||||||
|
// according to its own slack. Children sum is the maximum child size.
|
||||||
|
|
||||||
|
f32 margin = box->style.layout.margin.c[axis];
|
||||||
|
f32 parentAvailableSize = maximum(0, box->rect.c[2+axis] - box->spacing[axis] - 2*margin);
|
||||||
|
|
||||||
|
for_list(&box->children, child, ui_box, listElt)
|
||||||
|
{
|
||||||
|
ui_size* size = &child->style.size.c[axis];
|
||||||
|
if(size->kind == UI_SIZE_PARENT)
|
||||||
|
{
|
||||||
|
child->rect.c[2+axis] = parentAvailableSize * size->value;
|
||||||
|
}
|
||||||
|
else if(size->kind == UI_SIZE_PARENT_MINUS_PIXELS)
|
||||||
|
{
|
||||||
|
child->rect.c[2+axis] = maximum(0, parentAvailableSize - size->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ui_box_hidden(child) && !child->style.floating.c[axis])
|
||||||
|
{
|
||||||
|
f32 totalContents = child->rect.c[2+axis] + 2*box->style.layout.margin.c[axis];
|
||||||
|
f32 excess = ClampLowBound(totalContents - box->rect.c[2+axis], 0);
|
||||||
|
|
||||||
|
f32 relax = child->style.size.c[axis].relax;
|
||||||
|
child->rect.c[2+axis] -= minimum(excess, child->rect.c[2+axis]*relax);
|
||||||
|
|
||||||
|
sum = maximum(sum, child->rect.c[2+axis]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box->childrenSum[axis] = sum;
|
||||||
|
|
||||||
|
//NOTE: recurse in children
|
||||||
|
for_list(&box->children, child, ui_box, listElt)
|
||||||
|
{
|
||||||
|
ui_layout_solve_conflicts(ui, child, axis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_layout_compute_rect(ui_context* ui, ui_box* box, vec2 pos)
|
void ui_layout_compute_rect(ui_context* ui, ui_box* box, vec2 pos)
|
||||||
|
|
3
src/ui.h
3
src/ui.h
|
@ -85,6 +85,7 @@ typedef enum ui_size_kind
|
||||||
UI_SIZE_PIXELS,
|
UI_SIZE_PIXELS,
|
||||||
UI_SIZE_CHILDREN,
|
UI_SIZE_CHILDREN,
|
||||||
UI_SIZE_PARENT,
|
UI_SIZE_PARENT,
|
||||||
|
UI_SIZE_PARENT_MINUS_PIXELS,
|
||||||
|
|
||||||
} ui_size_kind;
|
} ui_size_kind;
|
||||||
|
|
||||||
|
@ -92,7 +93,7 @@ typedef struct ui_size
|
||||||
{
|
{
|
||||||
ui_size_kind kind;
|
ui_size_kind kind;
|
||||||
f32 value;
|
f32 value;
|
||||||
f32 strictness;
|
f32 relax;
|
||||||
} ui_size;
|
} ui_size;
|
||||||
|
|
||||||
typedef union ui_box_size
|
typedef union ui_box_size
|
||||||
|
|
Loading…
Reference in New Issue