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 bg; // background color Color fg; // foreground color Color primary; // primary color Color secondary; // secondary color Color accent; // accent color ushort radius; short size; } const Style DEFAULT_STYLE = { .margin = {2, 2, 2, 2}, .border = {2, 2, 2, 2}, .padding = {1, 1, 1, 1}, .radius = 12, .size = 16, .bg = 0x282828ffu.@to_rgba(), .fg = 0xfbf1c7ffu.@to_rgba(), .primary = 0xcc241dffu.@to_rgba(), .secondary = 0x458588ffu.@to_rgba(), .accent = 0xfabd2fffu.@to_rgba(), }; // 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 s) { // io::eprintfn("WARNING: style %x not found, using default style", id); 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++; // set the default style correctly 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 *