corrected layout offset
This commit is contained in:
parent
d33d72a074
commit
622b648d26
@ -308,7 +308,8 @@ $if DEBUG == 1:
|
||||
$endif
|
||||
|
||||
// sort the command buffer by the z-index
|
||||
ctx.cmd_queue.sort()!;
|
||||
// FIXME: sorting the buffer fucks with scissor commands that have to be kept in place
|
||||
//ctx.cmd_queue.sort()!;
|
||||
|
||||
// foreach (i, c: ctx.cmd_queue) {
|
||||
// io::printf("[%d]: ", i);
|
||||
|
@ -88,12 +88,12 @@ macro Point Layout.get_dimensions(&el)
|
||||
// GROSS HACK FOR EXACT DIMENSIONS
|
||||
if (el.w.@is_exact()) dim.x = el.w.min + el.content_offset.x + el.content_offset.w;
|
||||
if (el.h.@is_exact()) dim.y = el.h.min + el.content_offset.y + el.content_offset.h;
|
||||
|
||||
|
||||
// GROSS HACK FOR GROW DIMENSIONS
|
||||
// FIXME: does this always work?
|
||||
if (el.w.@is_grow()) dim.x = 0;
|
||||
if (el.h.@is_grow()) dim.y = 0;
|
||||
|
||||
|
||||
return dim;
|
||||
}
|
||||
|
||||
@ -106,17 +106,6 @@ macro Point Elem.content_space(&e)
|
||||
};
|
||||
}
|
||||
|
||||
// Update the parent element's grow children counter
|
||||
fn void update_parent_grow(Elem* child, Elem* parent)
|
||||
{
|
||||
switch (parent.layout.dir) {
|
||||
case ROW:
|
||||
if (child.layout.w.@is_grow()) parent.layout.grow_children++;
|
||||
case COLUMN:
|
||||
if (child.layout.h.@is_grow()) parent.layout.grow_children++;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the parent element's children size
|
||||
fn void update_parent_size(Elem* child, Elem* parent)
|
||||
{
|
||||
@ -129,9 +118,11 @@ fn void update_parent_size(Elem* child, Elem* parent)
|
||||
case ROW: // on rows grow the ch width by the child width and only grow ch height if it exceeds
|
||||
pl.children.w += @exact(child_size.x);
|
||||
pl.children.h = pl.children.h.comb_max(@exact(child_size.y));
|
||||
if (child.layout.w.@is_grow()) parent.layout.grow_children++;
|
||||
case COLUMN: // do the opposite on column
|
||||
pl.children.w = pl.children.w.comb_max(@exact(child_size.x));
|
||||
pl.children.h += @exact(child_size.y);
|
||||
if (child.layout.h.@is_grow()) parent.layout.grow_children++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,8 +178,6 @@ fn void resolve_grow_elements(Elem* e, Elem* p)
|
||||
if (e.layout.w.@is_grow()) {
|
||||
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);
|
||||
// the space slot accounts for the total size, while the element bounds does not account
|
||||
// for the margin
|
||||
e.bounds.w = slot;
|
||||
p.layout.grow_children--;
|
||||
p.layout.occupied += slot;
|
||||
@ -216,8 +205,8 @@ fn void resolve_placement(Elem* c, Elem* p)
|
||||
Layout* cl = &c.layout;
|
||||
|
||||
Point off = {
|
||||
.x = p.bounds.x + pl.origin.x,
|
||||
.y = p.bounds.y + pl.origin.y,
|
||||
.x = p.bounds.x + pl.origin.x + pl.content_offset.x,
|
||||
.y = p.bounds.y + pl.origin.y + pl.content_offset.y,
|
||||
};
|
||||
|
||||
switch (pl.anchor) {
|
||||
@ -226,7 +215,7 @@ fn void resolve_placement(Elem* c, Elem* p)
|
||||
c.bounds.y = off.y;
|
||||
case LEFT:
|
||||
c.bounds.x = off.x;
|
||||
c.bounds.y = off.y + p.bounds.h/2;
|
||||
c.bounds.y = off.y + p.content_space().y/2;
|
||||
if (pl.dir == COLUMN) {
|
||||
c.bounds.y -= pl.occupied/2;
|
||||
} else if (pl.dir == ROW) {
|
||||
@ -234,15 +223,15 @@ fn void resolve_placement(Elem* c, Elem* p)
|
||||
}
|
||||
case BOTTOM_LEFT:
|
||||
c.bounds.x = off.x;
|
||||
c.bounds.y = off.y + p.bounds.h ;
|
||||
c.bounds.y = off.y + p.content_space().y ;
|
||||
if (pl.dir == COLUMN) {
|
||||
c.bounds.y -= pl.occupied;
|
||||
} else if (pl.dir == ROW) {
|
||||
c.bounds.y -= c.bounds.h;
|
||||
}
|
||||
case BOTTOM:
|
||||
c.bounds.x = off.x + p.bounds.w/2;
|
||||
c.bounds.y = off.y + p.bounds.h;
|
||||
c.bounds.x = off.x + p.content_space().x/2;
|
||||
c.bounds.y = off.y + p.content_space().y;
|
||||
if (pl.dir == COLUMN) {
|
||||
c.bounds.y -= pl.occupied;
|
||||
c.bounds.x -= c.bounds.w/2;
|
||||
@ -251,8 +240,8 @@ fn void resolve_placement(Elem* c, Elem* p)
|
||||
c.bounds.x -= pl.occupied/2;
|
||||
}
|
||||
case BOTTOM_RIGHT:
|
||||
c.bounds.x = off.x + p.bounds.w;
|
||||
c.bounds.y = off.y + p.bounds.h;
|
||||
c.bounds.x = off.x + p.content_space().x;
|
||||
c.bounds.y = off.y + p.content_space().y;
|
||||
if (pl.dir == COLUMN) {
|
||||
c.bounds.y -= pl.occupied;
|
||||
c.bounds.x -= c.bounds.w;
|
||||
@ -261,8 +250,8 @@ fn void resolve_placement(Elem* c, Elem* p)
|
||||
c.bounds.x -= pl.occupied;
|
||||
}
|
||||
case RIGHT:
|
||||
c.bounds.x = off.x + p.bounds.w;
|
||||
c.bounds.y = off.y + p.bounds.h/2;
|
||||
c.bounds.x = off.x + p.content_space().x;
|
||||
c.bounds.y = off.y + p.content_space().y/2;
|
||||
if (pl.dir == COLUMN) {
|
||||
c.bounds.y -= pl.occupied/2;
|
||||
c.bounds.x -= c.bounds.w;
|
||||
@ -271,7 +260,7 @@ fn void resolve_placement(Elem* c, Elem* p)
|
||||
c.bounds.x -= pl.occupied;
|
||||
}
|
||||
case TOP_RIGHT:
|
||||
c.bounds.x = off.x + p.bounds.w;
|
||||
c.bounds.x = off.x + p.content_space().x;
|
||||
c.bounds.y = off.y;
|
||||
if (pl.dir == COLUMN) {
|
||||
c.bounds.x -= c.bounds.w;
|
||||
@ -279,7 +268,7 @@ fn void resolve_placement(Elem* c, Elem* p)
|
||||
c.bounds.x -= pl.occupied;
|
||||
}
|
||||
case TOP:
|
||||
c.bounds.x = off.x + p.bounds.w/2;
|
||||
c.bounds.x = off.x + p.content_space().x/2;
|
||||
c.bounds.y = off.y;
|
||||
if (pl.dir == COLUMN) {
|
||||
c.bounds.x -= c.bounds.w/2;
|
||||
@ -287,8 +276,8 @@ fn void resolve_placement(Elem* c, Elem* p)
|
||||
c.bounds.x -= pl.occupied/2;
|
||||
}
|
||||
case CENTER:
|
||||
c.bounds.x = off.x + p.bounds.w/2;
|
||||
c.bounds.y = off.y + p.bounds.h/2;
|
||||
c.bounds.x = off.x + p.content_space().x/2;
|
||||
c.bounds.y = off.y + p.content_space().y/2;
|
||||
if (pl.dir == COLUMN) {
|
||||
c.bounds.x -= c.bounds.w/2;
|
||||
c.bounds.y -= pl.occupied/2;
|
||||
@ -314,9 +303,7 @@ fn void Ctx.layout_element_tree(&ctx)
|
||||
isz 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))!!;
|
||||
// offset the origin by the margin
|
||||
p.layout.origin.x = p.layout.content_offset.x;
|
||||
p.layout.origin.y = p.layout.content_offset.y;
|
||||
//if (ctx.tree.is_root(current)!!) p = &&{};
|
||||
|
||||
// RESOLVE KNOWN DIMENSIONS
|
||||
isz ch_cur = 0;
|
||||
@ -349,7 +336,7 @@ fn void Ctx.layout_element_tree(&ctx)
|
||||
Elem* c = ctx.find_elem(ctx.tree.get(ch))!!;
|
||||
if (ctx.tree.is_root(ch)!!) {
|
||||
resolve_placement(p, &&{});
|
||||
update_children_bounds(c, p);
|
||||
update_children_bounds(p, &&{});
|
||||
} else {
|
||||
resolve_placement(c, p);
|
||||
update_children_bounds(c, p);
|
||||
|
@ -24,9 +24,9 @@ const Style DEFAULT_STYLE = {
|
||||
.margin = {2, 2, 2, 2},
|
||||
.border = {2, 2, 2, 2},
|
||||
.padding = {1, 1, 1, 1},
|
||||
.radius = 12,
|
||||
.radius = 0,
|
||||
.size = 16,
|
||||
|
||||
|
||||
.bg = 0x282828ffu.@to_rgba(),
|
||||
.fg = 0xfbf1c7ffu.@to_rgba(),
|
||||
.primary = 0xcc241dffu.@to_rgba(),
|
||||
@ -60,7 +60,7 @@ fn int StyleMap.import_style_string(&map, String text)
|
||||
Parser p;
|
||||
p.lex.text = text;
|
||||
int added;
|
||||
|
||||
|
||||
while (p.parse_style() == true) {
|
||||
added++;
|
||||
// set the default style correctly
|
||||
@ -79,7 +79,7 @@ fn int Ctx.import_style_from_file(&ctx, String path)
|
||||
text = mem::new_array(char, size);
|
||||
file::load_buffer(path, text)!!;
|
||||
defer mem::free(text);
|
||||
|
||||
|
||||
int added = ctx.import_style_from_string((String)text);
|
||||
return added;
|
||||
}
|
||||
@ -102,7 +102,7 @@ fn int Ctx.import_style_from_file(&ctx, String path)
|
||||
* The field "style name" will be hashed and the hash used as the id int the style map.
|
||||
* Fields may be excluded, each excluded field is set to zero.
|
||||
* The default unit is pixels, but millimeters is also available. The parser function accepts a scale
|
||||
* factor that has to be obtained with the window manager functions.
|
||||
* factor that has to be obtained with the window manager functions.
|
||||
*/
|
||||
|
||||
module ugui::css;
|
||||
@ -188,7 +188,7 @@ fn Token Lexer.next_token(&lex)
|
||||
// skip whitespace
|
||||
while (ascii::is_space_m(lex.peep())) {
|
||||
if (lex.advance() == 0) return {.type = EOF};
|
||||
if (lex.off >= lex.text.len) return {.type = EOF};
|
||||
if (lex.off >= lex.text.len) return {.type = EOF};
|
||||
}
|
||||
t.off = lex.off;
|
||||
|
||||
@ -216,7 +216,7 @@ fn Token Lexer.next_token(&lex)
|
||||
t.type = INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
char[10] hex_str = (char[])"0x";
|
||||
hex_str[2..] = lex.text[hex_start..lex.off-1];
|
||||
uint? color_hex = ((String)hex_str[..]).to_uint();
|
||||
@ -225,21 +225,21 @@ fn Token Lexer.next_token(&lex)
|
||||
break;
|
||||
}
|
||||
t.color = color_hex.to_rgba();
|
||||
|
||||
|
||||
case ascii::is_alpha_m(lex.peep()): // identifier
|
||||
t.type = IDENTIFIER;
|
||||
while (ascii::is_alnum_m(lex.peep()) || lex.peep() == '-' || lex.peep() == '_') {
|
||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||
}
|
||||
t.text = lex.text[t.off..lex.off-1];
|
||||
|
||||
|
||||
case ascii::is_digit_m(lex.peep()): // number
|
||||
t.type = NUMBER;
|
||||
t.unit = PIXELS;
|
||||
// find the end of the number
|
||||
usz end;
|
||||
while (ascii::is_alnum_m(lex.peep()) || lex.peep() == '+' || lex.peep() == '-' || lex.peep() == '.') {
|
||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||
}
|
||||
end = lex.off;
|
||||
if (end - t.off > 2) {
|
||||
@ -261,7 +261,7 @@ fn Token Lexer.next_token(&lex)
|
||||
t.value = value;
|
||||
t.text = lex.text[t.off..lex.off-1];
|
||||
}
|
||||
|
||||
|
||||
if (t.type == INVALID) {
|
||||
io::eprintfn("CSS Lexing ERROR at %d:%d: '%s' is not a valid token", t.line, t.col, lex.text[t.off..lex.off]);
|
||||
}
|
||||
@ -288,7 +288,7 @@ struct Parser {
|
||||
macro bool Parser.expect(&p, Token* t, TokenType type)
|
||||
{
|
||||
*t = p.lex.next_token();
|
||||
if (t.type == type) return true;
|
||||
if (t.type == type) return true;
|
||||
io::eprintfn("CSS parsing error at %d:%d: expected %s but got %s", t.line, t.col, type, t.type);
|
||||
return false;
|
||||
}
|
||||
@ -298,22 +298,22 @@ fn bool Parser.parse_style(&p)
|
||||
Token t;
|
||||
p.style = {};
|
||||
p.style_id = 0;
|
||||
|
||||
|
||||
// style name
|
||||
if (p.expect(&t, IDENTIFIER) == false) return false;
|
||||
p.style_id = t.text.hash();
|
||||
|
||||
// style body
|
||||
if (p.expect(&t, LCURLY) == false) return false;
|
||||
|
||||
|
||||
while (true) {
|
||||
if (p.parse_property() == false) return false;
|
||||
t = p.lex.peep_token();
|
||||
if (t.type != IDENTIFIER) break;
|
||||
}
|
||||
|
||||
|
||||
if (p.expect(&t, RCURLY) == false) return false;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -372,7 +372,7 @@ fn bool Parser.parse_property(&p)
|
||||
return false;
|
||||
}
|
||||
p.style.radius = (ushort)r;
|
||||
|
||||
|
||||
case "size":
|
||||
short s;
|
||||
if (p.parse_number(&s) == false) return false;
|
||||
@ -412,9 +412,9 @@ fn bool Parser.parse_size(&p, Rect* r)
|
||||
{
|
||||
short x;
|
||||
Token t;
|
||||
|
||||
|
||||
if (p.parse_number(&x) == false) return false;
|
||||
|
||||
|
||||
t = p.lex.peep_token();
|
||||
if (t.type == NUMBER) {
|
||||
// we got another number so we expect three more
|
||||
|
@ -44,7 +44,6 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
||||
elem.layout.text = ctx.measure_string(label)!;
|
||||
elem.layout.content_offset = style.margin + style.border + style.padding;
|
||||
|
||||
update_parent_grow(elem, parent);
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
@ -113,7 +112,6 @@ fn void? Ctx.checkbox_id(&ctx, Id id, String description, bool* active, String t
|
||||
elem.layout.text = ctx.measure_string(description)!;
|
||||
elem.layout.content_offset = style.margin + style.border + style.padding;
|
||||
|
||||
update_parent_grow(elem, parent);
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
@ -188,7 +186,6 @@ fn void? Ctx.toggle_id(&ctx, Id id, String description, bool* active)
|
||||
elem.layout.text = ctx.measure_string(description)!;
|
||||
elem.layout.content_offset = style.margin + style.border + style.padding;
|
||||
|
||||
update_parent_grow(elem, parent);
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
|
@ -68,10 +68,6 @@ fn void? Ctx.div_begin_id(&ctx,
|
||||
elem.div.scroll_size = slider_style.size ? slider_style.size : (style.size ? style.size : DEFAULT_STYLE.size);
|
||||
elem.div.z_index = parent.div.z_index + 1;
|
||||
|
||||
// update the ctx scissor
|
||||
ctx.div_scissor = elem.bounds;
|
||||
ctx.push_scissor(elem.bounds, elem.div.z_index)!;
|
||||
|
||||
// update layout with correct info
|
||||
elem.layout = {
|
||||
.w = width,
|
||||
@ -81,11 +77,12 @@ fn void? Ctx.div_begin_id(&ctx,
|
||||
.content_offset = style.margin + style.border + style.padding,
|
||||
};
|
||||
|
||||
// update parent grow children
|
||||
update_parent_grow(elem, parent);
|
||||
|
||||
ctx.push_rect(elem.bounds.pad(style.margin), elem.div.z_index, style)!;
|
||||
|
||||
// update the ctx scissor, it HAS to be after drawing the background
|
||||
ctx.div_scissor = elem.bounds.pad(elem.layout.content_offset);
|
||||
ctx.push_scissor(elem.bounds.pad(elem.layout.content_offset), elem.div.z_index)!;
|
||||
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
|
||||
// TODO: check active
|
||||
@ -132,7 +129,7 @@ fn Id? Ctx.div_end(&ctx)
|
||||
// the active_div returns to the parent of the current one
|
||||
ctx.active_div = ctx.tree.parentof(ctx.active_div)!;
|
||||
Elem* parent = ctx.get_parent()!;
|
||||
ctx.div_scissor = parent.bounds;
|
||||
ctx.div_scissor = parent.bounds.pad(parent.layout.content_offset);
|
||||
ctx.reset_scissor(elem.div.z_index)!;
|
||||
|
||||
update_parent_size(elem, parent);
|
||||
|
@ -29,7 +29,6 @@ fn ElemEvents? Ctx.slider_hor_id(&ctx, Id id, Size w, Size h, float* value, floa
|
||||
elem.layout.w = w;
|
||||
elem.layout.h = h;
|
||||
elem.layout.content_offset = style.margin + style.border + style.padding;
|
||||
update_parent_grow(elem, parent);
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
Rect bg_bounds = elem.bounds.pad(style.margin);
|
||||
@ -93,7 +92,6 @@ fn ElemEvents? Ctx.slider_ver_id(&ctx, Id id, Size w, Size h, float* value, floa
|
||||
elem.layout.w = w;
|
||||
elem.layout.h = h;
|
||||
elem.layout.content_offset = style.margin + style.border + style.padding;
|
||||
update_parent_grow(elem, parent);
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
// 2. Layout
|
||||
|
@ -19,7 +19,6 @@ fn void? Ctx.sprite_id(&ctx, Id id, String name)
|
||||
elem.layout.w = elem.layout.children.w = @exact(sprite.w);
|
||||
elem.layout.h = elem.layout.children.h = @exact(sprite.h);
|
||||
|
||||
update_parent_grow(elem, parent);
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
Id tex_id = ctx.sprite_atlas.id;
|
||||
|
@ -29,7 +29,6 @@ fn void? Ctx.text_id(&ctx, Id id, String text)
|
||||
elem.layout.text = elem.text.size;
|
||||
elem.layout.content_offset = style.margin + style.border + style.padding;
|
||||
|
||||
update_parent_grow(elem, parent);
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
ctx.layout_string(text, elem.bounds.pad(elem.layout.content_offset), TOP_LEFT, parent.div.z_index, style.fg)!;
|
||||
@ -47,7 +46,7 @@ fn ElemEvents? Ctx.text_box_id(&ctx, Id id, Size w, Size h, TextEdit* te)
|
||||
Style* style = ctx.styles.get_style(@str_hash("text-box"));
|
||||
|
||||
elem.text.te = te;
|
||||
|
||||
|
||||
Id text_hash = te.to_string().hash();
|
||||
if (elem.flags.is_new || elem.text.hash != text_hash) {
|
||||
elem.text.size = ctx.measure_string(te.to_string())!;
|
||||
@ -59,17 +58,17 @@ fn ElemEvents? Ctx.text_box_id(&ctx, Id id, Size w, Size h, TextEdit* te)
|
||||
elem.layout.text = elem.text.size;
|
||||
elem.layout.content_offset = style.margin + style.border + style.padding;
|
||||
|
||||
update_parent_grow(elem, parent);
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
// check input and update the text
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
|
||||
|
||||
if (elem.events.text_input || elem.events.key_press) {
|
||||
ctx.text_edit(elem.text.te);
|
||||
}
|
||||
|
||||
// draw the box
|
||||
|
||||
Rect bg_bounds = elem.bounds.pad(style.margin);
|
||||
Rect text_bounds = elem.bounds.pad(elem.layout.content_offset);
|
||||
ctx.push_rect(bg_bounds, parent.div.z_index, style)!;
|
||||
|
@ -7,6 +7,7 @@ default {
|
||||
border: 1;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
radius: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
|
@ -153,7 +153,7 @@ fn int main(String[] args)
|
||||
switch (e.type) {
|
||||
case EVENT_QUIT:
|
||||
quit = true;
|
||||
case EVENT_KEY_UP:
|
||||
case EVENT_KEY_UP:
|
||||
ui.input_key_release();
|
||||
nextcase;
|
||||
case EVENT_KEY_DOWN:
|
||||
|
Loading…
Reference in New Issue
Block a user