Remove OC_UI_FLAG_OVERFLOW_FIT.

Now OC_UI_FLAG_OVERFLOW_ALLOW controls both shrinking children to the parent's size and fitting parent to shrunk children size.
We can still emulate all combination of shrink * fit with this single flag (and sometimes a parent box).
This also makes fitting the default, which is more practical since fitting a box contents often requires fitting on all children.
This commit is contained in:
Martin Fouilleul 2023-09-15 19:45:44 +02:00
parent 623f5d4b84
commit fe69cedd45
3 changed files with 56 additions and 51 deletions

View File

@ -106,7 +106,7 @@ void column_begin(const char* header, f32 widthFraction)
| OC_UI_STYLE_BORDER_COLOR | OC_UI_STYLE_BORDER_COLOR
| OC_UI_STYLE_BORDER_SIZE | OC_UI_STYLE_BORDER_SIZE
| OC_UI_STYLE_ROUNDNESS); | OC_UI_STYLE_ROUNDNESS);
oc_ui_box_begin(header, OC_UI_FLAG_DRAW_BACKGROUND | OC_UI_FLAG_DRAW_BORDER | OC_UI_FLAG_OVERFLOW_FIT_X | OC_UI_FLAG_OVERFLOW_FIT_Y); oc_ui_box_begin(header, OC_UI_FLAG_DRAW_BACKGROUND | OC_UI_FLAG_DRAW_BORDER);
oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 }, oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 },
.layout.align.x = OC_UI_ALIGN_CENTER }, .layout.align.x = OC_UI_ALIGN_CENTER },
@ -128,7 +128,7 @@ void column_begin(const char* header, f32 widthFraction)
| OC_UI_STYLE_LAYOUT_ALIGN_X | OC_UI_STYLE_LAYOUT_ALIGN_X
| OC_UI_STYLE_LAYOUT_MARGIN_X | OC_UI_STYLE_LAYOUT_MARGIN_X
| OC_UI_STYLE_LAYOUT_SPACING); | OC_UI_STYLE_LAYOUT_SPACING);
oc_ui_box_begin("contents", OC_UI_FLAG_NONE | OC_UI_FLAG_OVERFLOW_FIT_X | OC_UI_FLAG_OVERFLOW_FIT_Y); oc_ui_box_begin("contents", OC_UI_FLAG_NONE);
} }
void column_end() void column_end()
@ -189,7 +189,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
.size.height = { OC_UI_SIZE_PARENT, 1, .minSize = 400 } }, .size.height = { OC_UI_SIZE_PARENT, 1, .minSize = 400 } },
OC_UI_STYLE_SIZE); OC_UI_STYLE_SIZE);
oc_ui_container("top level", OC_UI_FLAG_NONE | OC_UI_FLAG_OVERFLOW_FIT_Y) oc_ui_container("top level", OC_UI_FLAG_NONE)
{ {
//-------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------
// Menu bar // Menu bar
@ -228,7 +228,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
| OC_UI_STYLE_LAYOUT_MARGINS | OC_UI_STYLE_LAYOUT_MARGINS
| OC_UI_STYLE_LAYOUT_SPACING); | OC_UI_STYLE_LAYOUT_SPACING);
oc_ui_container("background", OC_UI_FLAG_DRAW_BACKGROUND | OC_UI_FLAG_OVERFLOW_FIT_Y) oc_ui_container("background", OC_UI_FLAG_DRAW_BACKGROUND)
{ {
column("Widgets", 1.0 / 3) column("Widgets", 1.0 / 3)
{ {
@ -239,7 +239,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
OC_UI_STYLE_SIZE_WIDTH OC_UI_STYLE_SIZE_WIDTH
| OC_UI_STYLE_LAYOUT_AXIS | OC_UI_STYLE_LAYOUT_AXIS
| OC_UI_STYLE_LAYOUT_SPACING); | OC_UI_STYLE_LAYOUT_SPACING);
oc_ui_container("top", OC_UI_FLAG_NONE | OC_UI_FLAG_OVERFLOW_FIT_X) oc_ui_container("top", OC_UI_FLAG_NONE)
{ {
oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_Y, oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_Y,
.layout.spacing = 24 }, .layout.spacing = 24 },
@ -555,13 +555,13 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
.layout.spacing = 32 }, .layout.spacing = 32 },
OC_UI_STYLE_LAYOUT_AXIS OC_UI_STYLE_LAYOUT_AXIS
| OC_UI_STYLE_LAYOUT_SPACING); | OC_UI_STYLE_LAYOUT_SPACING);
oc_ui_container("controls", OC_UI_FLAG_NONE | OC_UI_FLAG_OVERFLOW_FIT_X) oc_ui_container("controls", OC_UI_FLAG_NONE)
{ {
oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_Y, oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_Y,
.layout.spacing = 16 }, .layout.spacing = 16 },
OC_UI_STYLE_LAYOUT_AXIS OC_UI_STYLE_LAYOUT_AXIS
| OC_UI_STYLE_LAYOUT_SPACING); | OC_UI_STYLE_LAYOUT_SPACING);
oc_ui_container("unselected", OC_UI_FLAG_NONE | OC_UI_FLAG_OVERFLOW_FIT_X) oc_ui_container("unselected", OC_UI_FLAG_NONE)
{ {
oc_ui_style_next(&(oc_ui_style){ .fontSize = 16 }, oc_ui_style_next(&(oc_ui_style){ .fontSize = 16 },
OC_UI_STYLE_FONT_SIZE); OC_UI_STYLE_FONT_SIZE);
@ -569,7 +569,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
oc_ui_style_next(&(oc_ui_style){ .layout.spacing = 4 }, oc_ui_style_next(&(oc_ui_style){ .layout.spacing = 4 },
OC_UI_STYLE_LAYOUT_SPACING); OC_UI_STYLE_LAYOUT_SPACING);
oc_ui_container("size", OC_UI_FLAG_NONE | OC_UI_FLAG_OVERFLOW_FIT_X) oc_ui_container("size", OC_UI_FLAG_NONE)
{ {
f32 widthSlider = (unselectedWidth - 8) / 16; f32 widthSlider = (unselectedWidth - 8) / 16;
labeled_slider("Width", &widthSlider); labeled_slider("Width", &widthSlider);
@ -644,7 +644,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
.layout.spacing = 16 }, .layout.spacing = 16 },
OC_UI_STYLE_LAYOUT_AXIS OC_UI_STYLE_LAYOUT_AXIS
| OC_UI_STYLE_LAYOUT_SPACING); | OC_UI_STYLE_LAYOUT_SPACING);
oc_ui_container("selected", OC_UI_FLAG_NONE | OC_UI_FLAG_OVERFLOW_FIT_X) oc_ui_container("selected", OC_UI_FLAG_NONE)
{ {
oc_ui_style_next(&(oc_ui_style){ .fontSize = 16 }, oc_ui_style_next(&(oc_ui_style){ .fontSize = 16 },
OC_UI_STYLE_FONT_SIZE); OC_UI_STYLE_FONT_SIZE);
@ -652,7 +652,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
oc_ui_style_next(&(oc_ui_style){ .layout.spacing = 4 }, oc_ui_style_next(&(oc_ui_style){ .layout.spacing = 4 },
OC_UI_STYLE_LAYOUT_SPACING); OC_UI_STYLE_LAYOUT_SPACING);
oc_ui_container("size", OC_UI_FLAG_NONE | OC_UI_FLAG_OVERFLOW_FIT_X) oc_ui_container("size", OC_UI_FLAG_NONE)
{ {
f32 widthSlider = (selectedWidth - 8) / 16; f32 widthSlider = (selectedWidth - 8) / 16;
labeled_slider("Width", &widthSlider); labeled_slider("Width", &widthSlider);
@ -727,7 +727,7 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
.layout.spacing = 16 }, .layout.spacing = 16 },
OC_UI_STYLE_LAYOUT_AXIS OC_UI_STYLE_LAYOUT_AXIS
| OC_UI_STYLE_LAYOUT_SPACING); | OC_UI_STYLE_LAYOUT_SPACING);
oc_ui_container("label", OC_UI_FLAG_NONE | OC_UI_FLAG_OVERFLOW_FIT_X | OC_UI_FLAG_OVERFLOW_FIT_Y) oc_ui_container("label", OC_UI_FLAG_NONE)
{ {
oc_ui_style_next(&(oc_ui_style){ .fontSize = 16 }, oc_ui_style_next(&(oc_ui_style){ .fontSize = 16 },
OC_UI_STYLE_FONT_SIZE); OC_UI_STYLE_FONT_SIZE);

View File

@ -1092,7 +1092,7 @@ void oc_ui_layout_upward_dependent_size(oc_ui_context* ui, oc_ui_box* box, int a
} }
//NOTE: solve downard conflicts //NOTE: solve downard conflicts
int overflowAllowFlag = (OC_UI_FLAG_OVERFLOW_ALLOW_X << axis); int overflowFlag = (OC_UI_FLAG_OVERFLOW_ALLOW_X << axis);
if(box->style.layout.axis == axis) if(box->style.layout.axis == axis)
{ {
@ -1111,7 +1111,7 @@ void oc_ui_layout_upward_dependent_size(oc_ui_context* ui, oc_ui_box* box, int a
} }
} }
if(!(box->flags & overflowAllowFlag)) if(!(box->flags & overflowFlag))
{ {
//NOTE: then remove excess proportionally to each box slack //NOTE: then remove excess proportionally to each box slack
f32 totalContents = sum + box->spacing[axis] + 2 * box->style.layout.margin.c[axis]; f32 totalContents = sum + box->spacing[axis] + 2 * box->style.layout.margin.c[axis];
@ -1137,7 +1137,7 @@ void oc_ui_layout_upward_dependent_size(oc_ui_context* ui, oc_ui_box* box, int a
{ {
if(!oc_ui_box_hidden(child) && !child->style.floating.c[axis]) if(!oc_ui_box_hidden(child) && !child->style.floating.c[axis])
{ {
if(!(box->flags & overflowAllowFlag)) if(!(box->flags & overflowFlag))
{ {
f32 totalContents = child->rect.c[2 + axis] + 2 * box->style.layout.margin.c[axis]; f32 totalContents = child->rect.c[2 + axis] + 2 * box->style.layout.margin.c[axis];
f32 excess = oc_clamp_low(totalContents - box->rect.c[2 + axis], 0); f32 excess = oc_clamp_low(totalContents - box->rect.c[2 + axis], 0);
@ -1158,20 +1158,22 @@ void oc_ui_layout_upward_dependent_size(oc_ui_context* ui, oc_ui_box* box, int a
{ {
oc_ui_layout_upward_dependent_size(ui, child, axis); oc_ui_layout_upward_dependent_size(ui, child, axis);
if(box->style.layout.axis == axis) if(!oc_ui_box_hidden(child)
&& !child->style.floating.c[axis])
{ {
sum += child->rect.c[2 + axis]; if(box->style.layout.axis == axis)
} {
else sum += child->rect.c[2 + axis];
{ }
sum = oc_max(sum, child->rect.c[2 + axis]); else
{
sum = oc_max(sum, child->rect.c[2 + axis]);
}
} }
} }
box->childrenSum[axis] = sum; box->childrenSum[axis] = sum;
int overflowFitFlag = (OC_UI_FLAG_OVERFLOW_FIT_X << axis); if(!(box->flags & overflowFlag) && !oc_list_empty(box->children))
if(box->flags & overflowFitFlag)
{ {
f32 minSize = sum + 2 * box->style.layout.margin.c[axis] + box->spacing[axis]; f32 minSize = sum + 2 * box->style.layout.margin.c[axis] + box->spacing[axis];
box->rect.c[2 + axis] = oc_max(minSize, box->rect.c[2 + axis]); box->rect.c[2 + axis] = oc_max(minSize, box->rect.c[2 + axis]);
@ -1209,25 +1211,29 @@ void oc_ui_layout_upward_dependent_fixup(oc_ui_context* ui, oc_ui_box* box, int
} }
availableToParentSized -= child->rect.c[2 + axis]; availableToParentSized -= child->rect.c[2 + axis];
} }
availableToParentSized = oc_max(0, availableToParentSized);
oc_list_for(box->children, child, oc_ui_box, listElt) if(availableToParentSized && relaxSum)
{ {
oc_ui_size* size = &child->style.size.c[axis]; oc_list_for(box->children, child, oc_ui_box, listElt)
if(size->kind == OC_UI_SIZE_PARENT || size->kind == OC_UI_SIZE_PARENT_MINUS_PIXELS)
{ {
f32 wantedSize = 0; oc_ui_size* size = &child->style.size.c[axis];
if(size->kind == OC_UI_SIZE_PARENT) if(size->kind == OC_UI_SIZE_PARENT || size->kind == OC_UI_SIZE_PARENT_MINUS_PIXELS)
{ {
wantedSize = availableSize * size->value; f32 wantedSize = 0;
} if(size->kind == OC_UI_SIZE_PARENT)
else {
{ wantedSize = availableSize * size->value;
wantedSize = availableSize - size->value; }
} else
{
wantedSize = availableSize - size->value;
}
if(wantedSize > child->rect.c[2 + axis]) if(wantedSize > child->rect.c[2 + axis])
{ {
child->rect.c[2 + axis] += availableToParentSized * (size->relax / relaxSum); child->rect.c[2 + axis] += availableToParentSized * (size->relax / relaxSum);
}
} }
} }
} }
@ -1236,11 +1242,7 @@ void oc_ui_layout_upward_dependent_fixup(oc_ui_context* ui, oc_ui_box* box, int
oc_list_for(box->children, child, oc_ui_box, listElt) oc_list_for(box->children, child, oc_ui_box, listElt)
{ {
//TODO also give back to parent dependent in layout direction if parent has grown //TODO also give back to parent dependent in layout direction if parent has grown
if(axis != box->style.layout.axis)
if(axis == box->style.layout.axis)
{
}
else
{ {
oc_ui_size* size = &child->style.size.c[axis]; oc_ui_size* size = &child->style.size.c[axis];
if(size->kind == OC_UI_SIZE_PARENT) if(size->kind == OC_UI_SIZE_PARENT)
@ -1333,6 +1335,11 @@ void oc_ui_layout_compute_rect(oc_ui_context* ui, oc_ui_box* box, oc_vec2 pos)
currentPos.c[layoutAxis] += child->rect.c[2 + layoutAxis] + spacing; currentPos.c[layoutAxis] += child->rect.c[2 + layoutAxis] + spacing;
} }
} }
if(isnan(box->rect.w) || isnan(box->rect.h))
{
oc_log_error("error in box %.*s\n", oc_str8_ip(box->string));
OC_ASSERT(0);
}
} }
void oc_ui_layout_find_next_hovered_recursive(oc_ui_context* ui, oc_ui_box* box, oc_vec2 p) void oc_ui_layout_find_next_hovered_recursive(oc_ui_context* ui, oc_ui_box* box, oc_vec2 p)

View File

@ -477,18 +477,16 @@ typedef enum
OC_UI_FLAG_BLOCK_MOUSE = (1 << 3), OC_UI_FLAG_BLOCK_MOUSE = (1 << 3),
OC_UI_FLAG_HOT_ANIMATION = (1 << 4), OC_UI_FLAG_HOT_ANIMATION = (1 << 4),
OC_UI_FLAG_ACTIVE_ANIMATION = (1 << 5), OC_UI_FLAG_ACTIVE_ANIMATION = (1 << 5),
//WARN: these four following flags need to be kept as consecutive bits to //WARN: these two following flags need to be kept as consecutive bits to
// play well with axis-agnostic functions // play well with axis-agnostic functions
OC_UI_FLAG_OVERFLOW_ALLOW_X = (1 << 6), OC_UI_FLAG_OVERFLOW_ALLOW_X = (1 << 6),
OC_UI_FLAG_OVERFLOW_ALLOW_Y = (1 << 7), OC_UI_FLAG_OVERFLOW_ALLOW_Y = (1 << 7),
OC_UI_FLAG_OVERFLOW_FIT_X = (1 << 8), OC_UI_FLAG_CLIP = (1 << 8),
OC_UI_FLAG_OVERFLOW_FIT_Y = (1 << 9), OC_UI_FLAG_DRAW_BACKGROUND = (1 << 9),
OC_UI_FLAG_CLIP = (1 << 10), OC_UI_FLAG_DRAW_FOREGROUND = (1 << 10),
OC_UI_FLAG_DRAW_BACKGROUND = (1 << 11), OC_UI_FLAG_DRAW_BORDER = (1 << 11),
OC_UI_FLAG_DRAW_FOREGROUND = (1 << 12), OC_UI_FLAG_DRAW_TEXT = (1 << 12),
OC_UI_FLAG_DRAW_BORDER = (1 << 13), OC_UI_FLAG_DRAW_PROC = (1 << 13),
OC_UI_FLAG_DRAW_TEXT = (1 << 14),
OC_UI_FLAG_DRAW_PROC = (1 << 15),
OC_UI_FLAG_OVERLAY = (1 << 16), OC_UI_FLAG_OVERLAY = (1 << 16),
} oc_ui_flags; } oc_ui_flags;