in layout use a combined version of margin, border and padding
This commit is contained in:
parent
0f7d5a6506
commit
335624fcbe
@ -49,9 +49,7 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
|||||||
.max = (short)max(min_size, left_pad + icon_size.w + text_size.height.max + right_pad),
|
.max = (short)max(min_size, left_pad + icon_size.w + text_size.height.max + right_pad),
|
||||||
};
|
};
|
||||||
// add style border and padding
|
// add style border and padding
|
||||||
elem.layout.margin = style.margin;
|
elem.layout.content_offset = style.margin.add(style.border).add(style.padding);
|
||||||
elem.layout.border = style.border;
|
|
||||||
elem.layout.padding = style.padding;
|
|
||||||
|
|
||||||
elem.layout.children.w = elem.layout.w;
|
elem.layout.children.w = elem.layout.w;
|
||||||
elem.layout.children.h = elem.layout.h;
|
elem.layout.children.h = elem.layout.h;
|
||||||
@ -60,7 +58,7 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
|||||||
update_parent_size(elem, parent);
|
update_parent_size(elem, parent);
|
||||||
|
|
||||||
elem.events = ctx.get_elem_events(elem);
|
elem.events = ctx.get_elem_events(elem);
|
||||||
Rect content_bounds = elem.content_bounds(style);
|
Rect content_bounds = elem.content_bounds();
|
||||||
|
|
||||||
Rect text_bounds = {
|
Rect text_bounds = {
|
||||||
.x = content_bounds.x + icon_size.w + left_pad + inner_pad,
|
.x = content_bounds.x + icon_size.w + left_pad + inner_pad,
|
||||||
@ -85,7 +83,8 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
|||||||
s.bg = s.accent;
|
s.bg = s.accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.push_rect(elem.bounds, parent.div.z_index, &s)!;
|
Rect border_bounds = elem.bounds.pad(style.margin);
|
||||||
|
ctx.push_rect(border_bounds, parent.div.z_index, &s)!;
|
||||||
if (icon != "") {
|
if (icon != "") {
|
||||||
ctx.push_sprite(icon_bounds, sprite.uv(), ctx.sprite_atlas.id, parent.div.z_index, type: sprite.type)!;
|
ctx.push_sprite(icon_bounds, sprite.uv(), ctx.sprite_atlas.id, parent.div.z_index, type: sprite.type)!;
|
||||||
}
|
}
|
||||||
|
@ -78,15 +78,13 @@ fn void? Ctx.div_begin_id(&ctx,
|
|||||||
.h = height,
|
.h = height,
|
||||||
.dir = dir,
|
.dir = dir,
|
||||||
.anchor = anchor,
|
.anchor = anchor,
|
||||||
.margin = style.margin,
|
.content_offset = style.margin.add(style.border).add(style.padding),
|
||||||
.border = style.border,
|
|
||||||
.padding = style.padding,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// update parent grow children
|
// update parent grow children
|
||||||
update_parent_grow(elem, parent);
|
update_parent_grow(elem, parent);
|
||||||
|
|
||||||
ctx.push_rect(elem.bounds, elem.div.z_index, style)!;
|
ctx.push_rect(elem.bounds.pad(style.margin), elem.div.z_index, style)!;
|
||||||
|
|
||||||
elem.events = ctx.get_elem_events(elem);
|
elem.events = ctx.get_elem_events(elem);
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@ enum Anchor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Layout {
|
struct Layout {
|
||||||
Size w, h;
|
Size w, h; // size of the CONTENT, does not include margin, border and padding
|
||||||
struct children {
|
struct children { // the children size includes the children's margin/border/pading
|
||||||
Size w, h;
|
Size w, h;
|
||||||
}
|
}
|
||||||
ushort grow_children;
|
ushort grow_children;
|
||||||
@ -32,24 +32,22 @@ struct Layout {
|
|||||||
}
|
}
|
||||||
LayoutDirection dir;
|
LayoutDirection dir;
|
||||||
Anchor anchor;
|
Anchor anchor;
|
||||||
// FIXME: all this cruft with margin border and padding could be resolved by simply providing
|
Rect content_offset; // combined effect of margin, border and padding
|
||||||
// a "Rect content_offset" that represents the combined effect of all three above
|
|
||||||
Rect margin, border, padding;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Total width of a layout element, complete with margin, border and padding
|
// Total width of a layout element, complete with margin, border and padding
|
||||||
macro Size Layout.total_width(&el)
|
macro Size Layout.total_width(&el)
|
||||||
{
|
{
|
||||||
Rect min = (Rect){.w = el.w.min, .h = el.h.min}.expand(el.margin).expand(el.border).expand(el.padding);
|
Rect min = (Rect){.w = el.w.min, .h = el.h.min}.expand(el.content_offset);
|
||||||
Rect max = (Rect){.w = el.w.max, .h = el.h.max}.expand(el.margin).expand(el.border).expand(el.padding);
|
Rect max = (Rect){.w = el.w.max, .h = el.h.max}.expand(el.content_offset);
|
||||||
return {.min = min.w, .max = max.w};
|
return {.min = min.w, .max = max.w};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Total height of a layout element, complete with margin, border and padding
|
// Total height of a layout element, complete with margin, border and padding
|
||||||
macro Size Layout.total_height(&el)
|
macro Size Layout.total_height(&el)
|
||||||
{
|
{
|
||||||
Rect min = (Rect){.w = el.w.min, .h = el.h.min}.expand(el.margin).expand(el.border).expand(el.padding);
|
Rect min = (Rect){.w = el.w.min, .h = el.h.min}.expand(el.content_offset);
|
||||||
Rect max = (Rect){.w = el.w.max, .h = el.h.max}.expand(el.margin).expand(el.border).expand(el.padding);
|
Rect max = (Rect){.w = el.w.max, .h = el.h.max}.expand(el.content_offset);
|
||||||
return {.min = min.h, .max = max.h};
|
return {.min = min.h, .max = max.h};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,8 +55,8 @@ macro Size Layout.total_height(&el)
|
|||||||
macro Point Elem.content_space(&e)
|
macro Point Elem.content_space(&e)
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
.x = e.bounds.w - e.layout.border.x - e.layout.border.w - e.layout.padding.x - e.layout.padding.w,
|
.x = e.bounds.w - e.layout.content_offset.x - e.layout.content_offset.w,
|
||||||
.y = e.bounds.h - e.layout.border.y - e.layout.border.h - e.layout.padding.y - e.layout.padding.h,
|
.y = e.bounds.h - e.layout.content_offset.y - e.layout.content_offset.h,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +92,7 @@ fn void update_children_bounds(Elem* child, Elem* parent)
|
|||||||
parent.children_bounds = containing_rect(child.bounds, parent.bounds);
|
parent.children_bounds = containing_rect(child.bounds, parent.bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro Rect Elem.content_bounds(&elem, style) => elem.bounds.pad(style.border).pad(style.padding);
|
macro Rect Elem.content_bounds(&elem) => elem.bounds.pad(elem.layout.content_offset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
macro Rect Elem.get_view(&elem)
|
macro Rect Elem.get_view(&elem)
|
||||||
@ -120,16 +118,11 @@ macro Point Elem.get_view_off(&elem)
|
|||||||
// Assign the width and height of an element in the directions that it doesn't need to grow
|
// Assign the width and height of an element in the directions that it doesn't need to grow
|
||||||
fn void resolve_dimensions(Elem* e, Elem* p)
|
fn void resolve_dimensions(Elem* e, Elem* p)
|
||||||
{
|
{
|
||||||
// The element's border and paddign total width and height
|
|
||||||
Point m_tot = {.x = e.layout.margin.x + e.layout.margin.w, .y = e.layout.margin.y + e.layout.margin.h};
|
|
||||||
Point b_tot = {.x = e.layout.border.x + e.layout.border.w, .y = e.layout.border.y + e.layout.border.h};
|
|
||||||
Point p_tot = {.x = e.layout.padding.x + e.layout.padding.w, .y = e.layout.padding.y + e.layout.padding.h};
|
|
||||||
|
|
||||||
// ASSIGN WIDTH
|
// ASSIGN WIDTH
|
||||||
switch {
|
switch {
|
||||||
case e.layout.w.@is_exact():
|
case e.layout.w.@is_exact():
|
||||||
// if width is exact then assign it to the bounds and add border and paddign
|
// if width is exact then assign it to the bounds
|
||||||
e.bounds.w = e.layout.w.min + b_tot.x + p_tot.x;
|
e.bounds.w = e.layout.total_width().min;
|
||||||
case e.layout.w.@is_grow():
|
case e.layout.w.@is_grow():
|
||||||
// done in another pass
|
// done in another pass
|
||||||
break;
|
break;
|
||||||
@ -140,20 +133,10 @@ fn void resolve_dimensions(Elem* e, Elem* p)
|
|||||||
|
|
||||||
if (combined.min <= combined.max) { // OK!
|
if (combined.min <= combined.max) { // OK!
|
||||||
// the final element width is the content width plus padding and border
|
// the final element width is the content width plus padding and border
|
||||||
e.bounds.w = min(elem_width.max, children_width.max) + b_tot.x + p_tot.x;
|
e.bounds.w = min(elem_width.max, children_width.max) + e.layout.content_offset.x + e.layout.content_offset.w;
|
||||||
} else {
|
} else {
|
||||||
unreachable("Cannot fit children width: min:%d max:%d", combined.min, combined.max);
|
unreachable("Cannot fit children width: min:%d max:%d", combined.min, combined.max);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
Size w = e.needed_width().combine(e.layout.children.w);
|
|
||||||
if (w.max >= w.min) { // OK!
|
|
||||||
e.bounds.w = w.min;
|
|
||||||
} else {
|
|
||||||
println(e.needed_width(), " ", e.needed_height());
|
|
||||||
println(e.layout.children.w, " ", e.layout.children.h);
|
|
||||||
unreachable("Cannot fit children width: min:%d max:%d", w.min, w.max);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
default: unreachable("width is not exact, grow or fit");
|
default: unreachable("width is not exact, grow or fit");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +144,7 @@ fn void resolve_dimensions(Elem* e, Elem* p)
|
|||||||
switch {
|
switch {
|
||||||
case e.layout.h.@is_exact():
|
case e.layout.h.@is_exact():
|
||||||
// if width is exact then assign it to the bounds and add border and paddign
|
// if width is exact then assign it to the bounds and add border and paddign
|
||||||
e.bounds.h = e.layout.h.min + b_tot.y + p_tot.y;
|
e.bounds.h = e.layout.total_height().min;
|
||||||
case e.layout.h.@is_grow():
|
case e.layout.h.@is_grow():
|
||||||
break;
|
break;
|
||||||
// done in another pass
|
// done in another pass
|
||||||
@ -172,47 +155,34 @@ fn void resolve_dimensions(Elem* e, Elem* p)
|
|||||||
|
|
||||||
if (combined.min <= combined.max) { // OK!
|
if (combined.min <= combined.max) { // OK!
|
||||||
// the final element width is the content width plus padding and border
|
// the final element width is the content width plus padding and border
|
||||||
e.bounds.h = min(elem_height.max, children_height.max) + b_tot.y + p_tot.y;
|
e.bounds.h = min(elem_height.max, children_height.max) + e.layout.content_offset.y + e.layout.content_offset.h;
|
||||||
} else {
|
} else {
|
||||||
unreachable("Cannot fit children height: min:%d max:%d", combined.min, combined.max);
|
unreachable("Cannot fit children height: min:%d max:%d", combined.min, combined.max);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
Size h = e.needed_height().combine(e.layout.children.h);
|
|
||||||
if (h.max >= h.min) { // OK!
|
|
||||||
e.bounds.h = h.max;
|
|
||||||
} else {
|
|
||||||
unreachable("Cannot fit children height: min:%d max:%d", h.min, h.max);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
default: unreachable("width is not exact, grow or fit");
|
default: unreachable("width is not exact, grow or fit");
|
||||||
}
|
}
|
||||||
|
|
||||||
// the occupied space must account for the element's margin as well
|
|
||||||
switch (p.layout.dir) {
|
switch (p.layout.dir) {
|
||||||
case ROW:
|
case ROW:
|
||||||
if (!e.layout.w.@is_grow()) p.layout.occupied += e.bounds.w + m_tot.x;
|
if (!e.layout.w.@is_grow()) p.layout.occupied += e.bounds.w;
|
||||||
case COLUMN:
|
case COLUMN:
|
||||||
if (!e.layout.h.@is_grow()) p.layout.occupied += e.bounds.h + m_tot.y;
|
if (!e.layout.h.@is_grow()) p.layout.occupied += e.bounds.h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void resolve_grow_elements(Elem* e, Elem* p)
|
fn void resolve_grow_elements(Elem* e, Elem* p)
|
||||||
{
|
{
|
||||||
Point m_tot = {.x = e.layout.margin.x + e.layout.margin.w, .y = e.layout.margin.y + e.layout.margin.h};
|
|
||||||
Point b_tot = {.x = e.layout.border.x + e.layout.border.w, .y = e.layout.border.y + e.layout.border.h};
|
|
||||||
Point p_tot = {.x = e.layout.padding.x + e.layout.padding.w, .y = e.layout.padding.y + e.layout.padding.h};
|
|
||||||
|
|
||||||
// WIDTH
|
// WIDTH
|
||||||
if (e.layout.w.@is_grow()) {
|
if (e.layout.w.@is_grow()) {
|
||||||
if (p.layout.dir == ROW) { // grow along the axis, divide the parent size
|
if (p.layout.dir == ROW) { // grow along the axis, divide the parent size
|
||||||
short slot = (short)((p.content_space().x - p.layout.occupied) / p.layout.grow_children);
|
short slot = (short)((p.content_space().x - p.layout.occupied) / p.layout.grow_children);
|
||||||
// the space slot accounts for the total size, while the element bounds does not account
|
// the space slot accounts for the total size, while the element bounds does not account
|
||||||
// for the margin
|
// for the margin
|
||||||
e.bounds.w = slot - m_tot.x;
|
e.bounds.w = slot;
|
||||||
p.layout.grow_children--;
|
p.layout.grow_children--;
|
||||||
p.layout.occupied += slot;
|
p.layout.occupied += slot;
|
||||||
} else if (p.layout.dir == COLUMN) { // grow across the layout axis, inherit width of the parent
|
} else if (p.layout.dir == COLUMN) { // grow across the layout axis, inherit width of the parent
|
||||||
e.bounds.w = p.content_space().x - m_tot.x;
|
e.bounds.w = p.content_space().x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,11 +190,11 @@ fn void resolve_grow_elements(Elem* e, Elem* p)
|
|||||||
if (e.layout.h.@is_grow()) {
|
if (e.layout.h.@is_grow()) {
|
||||||
if (p.layout.dir == COLUMN) { // grow along the axis, divide the parent size
|
if (p.layout.dir == COLUMN) { // grow along the axis, divide the parent size
|
||||||
short slot = (short)((p.content_space().y - p.layout.occupied) / p.layout.grow_children);
|
short slot = (short)((p.content_space().y - p.layout.occupied) / p.layout.grow_children);
|
||||||
e.bounds.h = slot - m_tot.y;
|
e.bounds.h = slot;
|
||||||
p.layout.grow_children--;
|
p.layout.grow_children--;
|
||||||
p.layout.occupied += slot;
|
p.layout.occupied += slot;
|
||||||
} else if (p.layout.dir == ROW) { // grow across the layout axis, inherit width of the parent
|
} else if (p.layout.dir == ROW) { // grow across the layout axis, inherit width of the parent
|
||||||
e.bounds.h = p.content_space().y - m_tot.y;
|
e.bounds.h = p.content_space().y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,8 +205,8 @@ fn void resolve_placement(Elem* c, Elem* p)
|
|||||||
Layout* cl = &c.layout;
|
Layout* cl = &c.layout;
|
||||||
|
|
||||||
Point off = {
|
Point off = {
|
||||||
.x = p.bounds.x + pl.origin.x + cl.margin.x,
|
.x = p.bounds.x + pl.origin.x,
|
||||||
.y = p.bounds.y + pl.origin.y + cl.margin.x,
|
.y = p.bounds.y + pl.origin.y,
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (pl.anchor) {
|
switch (pl.anchor) {
|
||||||
@ -320,9 +290,9 @@ fn void resolve_placement(Elem* c, Elem* p)
|
|||||||
|
|
||||||
switch (pl.dir) {
|
switch (pl.dir) {
|
||||||
case ROW:
|
case ROW:
|
||||||
pl.origin.x += c.bounds.w + cl.margin.x + cl.margin.w;
|
pl.origin.x += c.bounds.w;
|
||||||
case COLUMN:
|
case COLUMN:
|
||||||
pl.origin.y += c.bounds.h + cl.margin.x + cl.margin.w;
|
pl.origin.y += c.bounds.h;
|
||||||
default: unreachable("unknown layout direction");
|
default: unreachable("unknown layout direction");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,8 +306,8 @@ fn void Ctx.layout_element_tree(&ctx)
|
|||||||
for (; current >= 0; current = ctx.tree.level_order_it(0, &cursor)!!) {
|
for (; current >= 0; current = ctx.tree.level_order_it(0, &cursor)!!) {
|
||||||
Elem* p = ctx.find_elem(ctx.tree.get(current))!!;
|
Elem* p = ctx.find_elem(ctx.tree.get(current))!!;
|
||||||
// offset the origin by the margin
|
// offset the origin by the margin
|
||||||
p.layout.origin.x = p.layout.border.x + p.layout.padding.x;
|
p.layout.origin.x = p.layout.content_offset.x;
|
||||||
p.layout.origin.y = p.layout.border.y + p.layout.padding.y;
|
p.layout.origin.y = p.layout.content_offset.y;
|
||||||
|
|
||||||
// RESOLVE KNOWN DIMENSIONS
|
// RESOLVE KNOWN DIMENSIONS
|
||||||
isz ch_cur = 0;
|
isz ch_cur = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user