From 9fc1d90455c2117346a688cb20a6888891cc26a7 Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Fri, 4 Jul 2025 11:17:42 +0200 Subject: [PATCH] simple style import with a subset of css --- lib/ugui.c3l/src/ugui_core.c3 | 29 +-- lib/ugui.c3l/src/ugui_shapes.c3 | 11 + lib/ugui.c3l/src/ugui_style.c3 | 402 ++++++++++++++++++++++++++++++++ src/main.c3 | 9 + 4 files changed, 430 insertions(+), 21 deletions(-) create mode 100644 lib/ugui.c3l/src/ugui_style.c3 diff --git a/lib/ugui.c3l/src/ugui_core.c3 b/lib/ugui.c3l/src/ugui_core.c3 index ae5cd5d..81c5ca6 100644 --- a/lib/ugui.c3l/src/ugui_core.c3 +++ b/lib/ugui.c3l/src/ugui_core.c3 @@ -6,6 +6,7 @@ import fifo; import std::io; import std::core::string; +import std::core::mem::allocator; // element ids are just long ints @@ -74,25 +75,14 @@ const uint MAX_CMDS = 2048; const uint ROOT_ID = 1; const uint TEXT_MAX = 64; -// global style, similar to the css box model -struct Style { // css box model - Rect padding; - Rect border; - Rect margin; - Color bgcolor; // background color - Color fgcolor; // foreground color - Color brcolor; // border color - ushort radius; -} - - struct Ctx { IdTree tree; ElemCache cache; CmdQueue cmd_queue; + StyleMap styles; // total size in pixels of the context ushort width, height; - Style style; + Style* style; // TODO: rename to "active_style" or something Font font; SpriteAtlas sprite_atlas; @@ -206,16 +196,12 @@ fn void? Ctx.init(&ctx) ctx.cmd_queue.init(MAX_CMDS)!; defer catch { (void)ctx.cmd_queue.free(); } + ctx.styles.init(allocator::heap()); + defer catch { ctx.styles.free(); } + ctx.active_div = 0; - // TODO: add style config - ctx.style.margin = {2, 2, 2, 2}; - ctx.style.border = {2, 2, 2, 2}; - ctx.style.padding = {1, 1, 1, 1}; - ctx.style.radius = 12; - ctx.style.bgcolor = 0x282828ffu.to_rgba(); - ctx.style.fgcolor = 0xfbf1c7ffu.to_rgba(); - ctx.style.brcolor = 0xd79921ffu.to_rgba(); + ctx.style = &DEFAULT_STYLE; } fn void Ctx.free(&ctx) @@ -225,6 +211,7 @@ fn void Ctx.free(&ctx) (void)ctx.cmd_queue.free(); (void)ctx.font.free(); (void)ctx.sprite_atlas.free(); + (void)ctx.styles.free(); } fn void? Ctx.frame_begin(&ctx) diff --git a/lib/ugui.c3l/src/ugui_shapes.c3 b/lib/ugui.c3l/src/ugui_shapes.c3 index 1bfb00a..9e778b7 100644 --- a/lib/ugui.c3l/src/ugui_shapes.c3 +++ b/lib/ugui.c3l/src/ugui_shapes.c3 @@ -203,6 +203,17 @@ macro Color uint.to_rgba(u) }; } + +macro Color uint.@to_rgba($u) +{ + return { + .r = (char)(($u >> 24) & 0xff), + .g = (char)(($u >> 16) & 0xff), + .b = (char)(($u >> 8) & 0xff), + .a = (char)(($u >> 0) & 0xff) + }; +} + macro uint Color.to_uint(c) { uint u = c.r | (c.g << 8) | (c.b << 16) | (c.a << 24); diff --git a/lib/ugui.c3l/src/ugui_style.c3 b/lib/ugui.c3l/src/ugui_style.c3 new file mode 100644 index 0000000..3899edb --- /dev/null +++ b/lib/ugui.c3l/src/ugui_style.c3 @@ -0,0 +1,402 @@ +module ugui; + +import std::collections::map; +import std::core::mem::allocator; +import std::io; + +// global style, similar to the css box model +struct Style { // css box model + Rect padding; + Rect border; + Rect margin; + Color bgcolor; // background color + Color fgcolor; // foreground color + Color brcolor; // border color + ushort radius; +} + +const Style DEFAULT_STYLE = { + .margin = {2, 2, 2, 2}, + .border = {2, 2, 2, 2}, + .padding = {1, 1, 1, 1}, + .bgcolor = 0x282828ffu.@to_rgba(), + .fgcolor = 0xfbf1c7ffu.@to_rgba(), + .brcolor = 0xd79921ffu.@to_rgba(), + .radius = 12, +}; + +// style is stored in a hashmap, each style has an Id that can be generated by a string or whatever +alias StyleMap = map::HashMap{Id, Style}; + +// push or update a new style into the map +fn void StyleMap.register_style(&map, Style* style, Id id) +{ + if (style == null) return; + map.set(id, *style); +} + +// get a style from the map, if the style is not found then use a default style. +fn Style* StyleMap.get_style(&map, Id id) +{ + Style*? s = map.get_ref(id); + if (catch e = s) { + return &DEFAULT_STYLE; + } + return s; +} + +fn int StyleMap.import_style_string(&map, String text) +{ + Parser p; + p.lex.text = text; + int added; + + while (p.parse_style() == true) { + added++; + map.register_style(&p.style, p.style_id); + if (p.lex.peep_token().type == EOF) break; + } + + return added; +} + +fn int Ctx.import_style_from_string(&ctx, String text) => ctx.styles.import_style_string(text); +fn int Ctx.import_style_from_file(&ctx, String path) +{ + char[] text; + usz size = file::get_size(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; +} + + +/* + * Style can be serialized and deserialized with a subset of CSS + *