diff --git a/lib/ugui.c3l/src/ugui_core.c3 b/lib/ugui.c3l/src/ugui_core.c3 index 4e797ae..04d8e06 100644 --- a/lib/ugui.c3l/src/ugui_core.c3 +++ b/lib/ugui.c3l/src/ugui_core.c3 @@ -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); diff --git a/lib/ugui.c3l/src/ugui_layout.c3 b/lib/ugui.c3l/src/ugui_layout.c3 index 4a2e5c7..a39771f 100644 --- a/lib/ugui.c3l/src/ugui_layout.c3 +++ b/lib/ugui.c3l/src/ugui_layout.c3 @@ -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); diff --git a/lib/ugui.c3l/src/ugui_style.c3 b/lib/ugui.c3l/src/ugui_style.c3 index e2fd54a..ecf55d2 100644 --- a/lib/ugui.c3l/src/ugui_style.c3 +++ b/lib/ugui.c3l/src/ugui_style.c3 @@ -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 diff --git a/lib/ugui.c3l/src/widgets/ugui_button.c3 b/lib/ugui.c3l/src/widgets/ugui_button.c3 index dc414da..8cee40b 100644 --- a/lib/ugui.c3l/src/widgets/ugui_button.c3 +++ b/lib/ugui.c3l/src/widgets/ugui_button.c3 @@ -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); diff --git a/lib/ugui.c3l/src/widgets/ugui_div.c3 b/lib/ugui.c3l/src/widgets/ugui_div.c3 index 2630f37..8e6e95e 100644 --- a/lib/ugui.c3l/src/widgets/ugui_div.c3 +++ b/lib/ugui.c3l/src/widgets/ugui_div.c3 @@ -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); diff --git a/lib/ugui.c3l/src/widgets/ugui_slider.c3 b/lib/ugui.c3l/src/widgets/ugui_slider.c3 index 9f28e96..5bc8038 100644 --- a/lib/ugui.c3l/src/widgets/ugui_slider.c3 +++ b/lib/ugui.c3l/src/widgets/ugui_slider.c3 @@ -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 diff --git a/lib/ugui.c3l/src/widgets/ugui_sprite.c3 b/lib/ugui.c3l/src/widgets/ugui_sprite.c3 index f0c8661..50e2ab8 100644 --- a/lib/ugui.c3l/src/widgets/ugui_sprite.c3 +++ b/lib/ugui.c3l/src/widgets/ugui_sprite.c3 @@ -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; diff --git a/lib/ugui.c3l/src/widgets/ugui_text.c3 b/lib/ugui.c3l/src/widgets/ugui_text.c3 index d4d4d28..6d365ea 100644 --- a/lib/ugui.c3l/src/widgets/ugui_text.c3 +++ b/lib/ugui.c3l/src/widgets/ugui_text.c3 @@ -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)!; diff --git a/resources/style.css b/resources/style.css index 3f3cea2..8fcef1a 100644 --- a/resources/style.css +++ b/resources/style.css @@ -7,6 +7,7 @@ default { border: 1; padding: 0; margin: 0; + radius: 0; } button { diff --git a/src/main.c3 b/src/main.c3 index 652019d..6fc447e 100644 --- a/src/main.c3 +++ b/src/main.c3 @@ -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: