correct placement and box model

c3
Alessandro Mauri 1 week ago
parent 250a0fb3b5
commit 763e9ba8d6
  1. 6
      src/main.c3
  2. 11
      src/ugui_data.c3
  3. 7
      src/ugui_div.c3
  4. 6
      src/ugui_impl.c3
  5. 93
      src/ugui_layout.c3

@ -53,15 +53,15 @@ fn int main(String[] args)
// main div, fill the whole window // main div, fill the whole window
ctx.div_begin("main", ugui::Rect{.w=ctx.width/2})!!; ctx.div_begin("main", ugui::Rect{.w=ctx.width/2})!!;
{| {|
ctx.layout_set_column()!!; ctx.layout_set_row()!!;
if (ctx.button("button0", ugui::Rect{0,0,30,30})!!.mouse_press) { if (ctx.button("button0", ugui::Rect{0,0,30,30})!!.mouse_press) {
io::printn("press button0"); io::printn("press button0");
} }
ctx.layout_next_column()!!; //ctx.layout_next_column()!!;
if (ctx.button("button1", ugui::Rect{0,0,30,30})!!.mouse_press) { if (ctx.button("button1", ugui::Rect{0,0,30,30})!!.mouse_press) {
io::printn("press button1"); io::printn("press button1");
} }
ctx.layout_next_column()!!; //ctx.layout_next_column()!!;
if (ctx.button("button2", ugui::Rect{0,0,30,30})!!.mouse_release) { if (ctx.button("button2", ugui::Rect{0,0,30,30})!!.mouse_release) {
io::printn("release button2"); io::printn("release button2");
} }

@ -52,6 +52,11 @@ enum DivLayout {
// div element // div element
struct Div { struct Div {
DivLayout layout; DivLayout layout;
bool can_scroll_x;
bool can_scroll_y;
isz vertical_scroll_bar;
isz horizontal_scroll_bar;
Rect children_bounds;
Point origin_r, origin_c; Point origin_r, origin_c;
Color color_bg; Color color_bg;
} }
@ -208,3 +213,9 @@ macro rect_intersection(Rect a, Rect b)
.h = (short)min(a.y+a.h, b.y+b.h) - (short)max(a.y, b.y), .h = (short)min(a.y+a.h, b.y+b.h) - (short)max(a.y, b.y),
}; };
} }
// rect intersection not null
macro rect_collision(Rect a, Rect b)
{
return !(a.x > b.x+b.w || a.x+a.w < b.x || a.y > b.y+b.h || a.y+a.h < b.y);
}

@ -17,6 +17,9 @@ fn void! Ctx.div_begin(&ctx, String label, Rect size)
if (c_elem.flags.is_new || parent.flags.updated) { if (c_elem.flags.is_new || parent.flags.updated) {
// 2. layout the element // 2. layout the element
c_elem.bounds = ctx.position_element(parent, size); c_elem.bounds = ctx.position_element(parent, size);
if (c_elem.flags.is_new) {
c_elem.div.children_bounds = c_elem.bounds;
}
// 3. Mark the element as updated // 3. Mark the element as updated
c_elem.flags.updated = true; c_elem.flags.updated = true;
@ -28,6 +31,10 @@ fn void! Ctx.div_begin(&ctx, String label, Rect size)
}; };
c_elem.div.color_bg = uint_to_rgba(0xff0000ff); c_elem.div.color_bg = uint_to_rgba(0xff0000ff);
c_elem.div.origin_r = c_elem.div.origin_c; c_elem.div.origin_r = c_elem.div.origin_c;
c_elem.div.can_scroll_x = false;
c_elem.div.can_scroll_y = false;
c_elem.div.vertical_scroll_bar = -1;
c_elem.div.horizontal_scroll_bar = -1;
} }
// Add the background to the draw stack // Add the background to the draw stack

@ -32,6 +32,12 @@ macro Ctx.get_elem_by_label(&ctx, String label)
return ctx.cache.search(id); return ctx.cache.search(id);
} }
macro Ctx.get_elem_by_tree_idx(&ctx, isz idx) @private
{
Id id = ctx.tree.get(ctx.active_div)!;
return ctx.cache.search(id);
}
fn void! Ctx.init(&ctx) fn void! Ctx.init(&ctx)
{ {
ctx.tree.init(MAX_ELEMENTS)!; ctx.tree.init(MAX_ELEMENTS)!;

@ -75,9 +75,12 @@ fn void! Ctx.layout_next_column(&ctx)
} }
// position the rectangle inside the parent according to the layout // position the rectangle inside the parent according to the layout
// parent: parent div
// rect: the requested size
// style: apply style
fn Rect Ctx.position_element(&ctx, Elem *parent, Rect rect, bool style = false) fn Rect Ctx.position_element(&ctx, Elem *parent, Rect rect, bool style = false)
{ {
Rect bounds; Rect placement;
Point origin; Point origin;
// 1. Select the right origin // 1. Select the right origin
@ -91,49 +94,65 @@ fn Rect Ctx.position_element(&ctx, Elem *parent, Rect rect, bool style = false)
// Error // Error
} }
// 2. Position the rect // the bottom-right border of the element box
bounds.x = (short)max(origin.x + rect.x, 0); Point pl_corner;
bounds.y = (short)max(origin.y + rect.y, 0);
// 3. Calculate width & height // 2. Calculate the placement
// FIXME: account for origin offset!! placement.x = (short)max(origin.x + rect.x, 0);
bounds.w = rect.w > 0 ? rect.w : parent.bounds.w; placement.y = (short)max(origin.y + rect.y, 0);
bounds.h = rect.h > 0 ? rect.h : parent.bounds.h; placement.w = rect.w > 0 ? rect.w : parent.bounds.w - (placement.x - parent.bounds.x);
placement.h = rect.h > 0 ? rect.h : parent.bounds.h - (placement.y - parent.bounds.y);
// 4. Update the origins of the parent pl_corner.x = placement.x + placement.w;
pl_corner.y = placement.y + placement.h;
// 2.1 apply style, css box model
if (style) {
Rect margin = ctx.style.margin;
Rect border = ctx.style.border;
Rect padding = ctx.style.padding;
placement.x += margin.x;
placement.y += margin.y;
if (rect.w != 0) { placement.w += margin.x+margin.w + padding.x+padding.w; }
if (rect.h != 0) { placement.h += margin.y+margin.h + padding.y+padding.h; }
pl_corner.x = placement.x + placement.w + margin.w;
pl_corner.y = placement.y + placement.h + margin.h;
}
// 3. Update the origins of the parent
parent.div.origin_r = Point{ parent.div.origin_r = Point{
.x = bounds.x + bounds.w, .x = pl_corner.x,
.y = bounds.y, .y = origin.y,
}; };
parent.div.origin_c = Point{ parent.div.origin_c = Point{
.x = bounds.x, .x = origin.x,
.y = bounds.y + bounds.h, .y = pl_corner.y,
}; };
// if using the style then apply margins // 4. Calculate the "scrolled" view
// FIXME: this does not work Point off;
if (style && parent.div.layout != LAYOUT_FLOATING) { if (parent.div.can_scroll_x && parent.div.horizontal_scroll_bar != -1) {
bounds.x += ctx.style.margin.x; Elem*! sx = ctx.get_elem_by_tree_idx(parent.div.horizontal_scroll_bar);
bounds.y += ctx.style.margin.y; if (catch sx) { return Rect{}; }
// TODO: assert that the element is a slider
// total keep-out borders off.x = (short)(parent.div.children_bounds.w * sx.slider.value);
Rect margin_tot = { }
.x = ctx.style.padding.x + ctx.style.border.x + if (parent.div.can_scroll_y && parent.div.vertical_scroll_bar != -1) {
ctx.style.margin.x, Elem*! sy = ctx.get_elem_by_tree_idx(parent.div.vertical_scroll_bar);
.y = ctx.style.padding.y + ctx.style.border.y + if (catch sy) { return Rect{}; }
ctx.style.margin.y, // TODO: assert that the element is a slider
.w = ctx.style.padding.w + ctx.style.border.x + off.y = (short)(parent.div.children_bounds.h * sy.slider.value);
ctx.style.margin.w,
.h = ctx.style.padding.h + ctx.style.border.x +
ctx.style.margin.h,
};
parent.div.origin_r.x += margin_tot.x + margin_tot.w;
// parent.div.origin_r.y += margin_tot.h;
// parent.div.origin_c.x += margin_tot.w;
parent.div.origin_c.y += margin_tot.y + margin_tot.h;
} }
Rect view = {
.x = parent.bounds.x + off.x,
.y = parent.bounds.y + off.y,
.w = parent.bounds.w,
.h = parent.bounds.h,
};
// TODO: 5. check if the placement is inside the view
return bounds; return placement;
} }

Loading…
Cancel
Save