From 48d1b295377aee4e83ff70cfefcda17dff5638cd Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Wed, 17 Sep 2025 22:45:03 +0200 Subject: [PATCH] first draft for absolute positioning --- lib/ugui.c3l/src/ugui_layout.c3 | 21 +++++++++++++++++++-- lib/ugui.c3l/src/widgets/ugui_div.c3 | 12 ++++++++++-- src/main.c3 | 11 +++-------- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/lib/ugui.c3l/src/ugui_layout.c3 b/lib/ugui.c3l/src/ugui_layout.c3 index a39771f..afdf0c5 100644 --- a/lib/ugui.c3l/src/ugui_layout.c3 +++ b/lib/ugui.c3l/src/ugui_layout.c3 @@ -31,8 +31,12 @@ struct Layout { struct origin { short x, y; } - LayoutDirection dir; - Anchor anchor; + // false: the element is laid out according to the parent + // true: the element is laid out separate from all other children and the relative position to + // the parent is the .origin field + bool absolute; + LayoutDirection dir; // the direction the children are laid out + Anchor anchor; // how the children are positioned Rect content_offset; // combined effect of margin, border and padding } @@ -112,6 +116,9 @@ fn void update_parent_size(Elem* child, Elem* parent) Layout* cl = &child.layout; Layout* pl = &parent.layout; + // if the element has absolute position do not update the parent + if (cl.absolute) return; + Point child_size = cl.get_dimensions(); switch (pl.dir) { @@ -163,6 +170,9 @@ fn void resolve_dimensions(Elem* e, Elem* p) Point elem_dimensions = el.get_dimensions(); e.bounds.w = elem_dimensions.x; e.bounds.h = elem_dimensions.y; + + // if the element has absolute position do not update the parent + if (el.absolute) return; switch (pl.dir) { case ROW: @@ -209,6 +219,13 @@ fn void resolve_placement(Elem* c, Elem* p) .y = p.bounds.y + pl.origin.y + pl.content_offset.y, }; + // if the element has absolute position assign the origin and do not update the parent + if (cl.absolute) { + c.bounds.x = p.bounds.x + pl.content_offset.x + cl.origin.x; + c.bounds.y = p.bounds.x + pl.content_offset.x + cl.origin.y; + return; + } + switch (pl.anchor) { case TOP_LEFT: c.bounds.x = off.x; diff --git a/lib/ugui.c3l/src/widgets/ugui_div.c3 b/lib/ugui.c3l/src/widgets/ugui_div.c3 index 8e6e95e..611e3d7 100644 --- a/lib/ugui.c3l/src/widgets/ugui_div.c3 +++ b/lib/ugui.c3l/src/widgets/ugui_div.c3 @@ -25,12 +25,13 @@ macro Ctx.@div(&ctx, Size width = @grow, Size height = @grow, LayoutDirection dir = ROW, Anchor anchor = TOP_LEFT, + bool absolute = false, Point off = {}, bool scroll_x = false, bool scroll_y = false, ...; @body() ) { - ctx.div_begin(width, height, dir, anchor, scroll_x, scroll_y, $vasplat)!; + ctx.div_begin(width, height, dir, anchor, absolute, off, scroll_x, scroll_y, $vasplat)!; @body(); return ctx.div_end()!; } @@ -39,11 +40,12 @@ macro Ctx.div_begin(&ctx, Size width = @grow(), Size height = @grow(), LayoutDirection dir = ROW, Anchor anchor = TOP_LEFT, + bool absolute = false, Point off = {}, bool scroll_x = false, bool scroll_y = false, ... ) { - return ctx.div_begin_id(@compute_id($vasplat), width, height, dir, anchor, scroll_x, scroll_y); + return ctx.div_begin_id(@compute_id($vasplat), width, height, dir, anchor, absolute, off, scroll_x, scroll_y); } fn void? Ctx.div_begin_id(&ctx, @@ -51,6 +53,7 @@ fn void? Ctx.div_begin_id(&ctx, Size width, Size height, LayoutDirection dir, Anchor anchor, + bool absolute, Point off, bool scroll_x, bool scroll_y ) { @@ -75,7 +78,12 @@ fn void? Ctx.div_begin_id(&ctx, .dir = dir, .anchor = anchor, .content_offset = style.margin + style.border + style.padding, + .absolute = absolute, }; + if (absolute) { + elem.layout.origin.x = off.x; + elem.layout.origin.y = off.y; + } ctx.push_rect(elem.bounds.pad(style.margin), elem.div.z_index, style)!; diff --git a/src/main.c3 b/src/main.c3 index 652bd89..b263365 100644 --- a/src/main.c3 +++ b/src/main.c3 @@ -216,15 +216,10 @@ $endswitch TimeStats dts = draw_times.get_stats(); TimeStats uts = ui_times.get_stats(); -/* - ui.layout_set_floating()!!; - ui.@div({0, ui.height-150, -300, 150}) { - ui.layout_set_column()!!; - ui.text_unbounded(string::tformat("frame %d, fps = %.2f", frame, fps))!!; - ui.text_unbounded(string::tformat("ui avg: %s\ndraw avg: %s\nTOT: %s", uts.avg, dts.avg, uts.avg+dts.avg))!!; - ui.text_unbounded(string::tformat("%s %s", mod.lctrl, (String)ui.input.keyboard.text[:ui.input.keyboard.text_len]))!!; + ui.@div(ugui::@fit(), ugui::@fit(), COLUMN, TOP_LEFT, true) { + ui.text(string::tformat("frame %d, fps = %.2f", frame, fps))!!; + ui.text(string::tformat("ui avg: %s\ndraw avg: %s\nTOT: %s", uts.avg, dts.avg, uts.avg+dts.avg))!!; }!!; -*/ ui.frame_end()!!; /* End UI Handling */