diff --git a/packages/ludic.ui/anim.ludic b/packages/ludic.ui/anim.ludic index 22932f41..1b5ed653 100644 --- a/packages/ludic.ui/anim.ludic +++ b/packages/ludic.ui/anim.ludic @@ -55,7 +55,7 @@ function an_apply(ui_st: mut UiState, n: UiNode) -> void { ui_err(ui_st, `animation {n.anim}: there is no @keyframes of that name`) return } - var t = (an_now(ui_st) - an_began(ui_st, `{n.key}@{n.anim}`)) / n.anim_dur + var t = (an_now(ui_st) - an_began(ui_st, mm_join(ui_st, n.key, "@", n.anim))) / n.anim_dur if n.anim_loop { let lap = int(t) t = t - float(lap) diff --git a/packages/ludic.ui/attr.ludic b/packages/ludic.ui/attr.ludic index fcd19c22..a5e13b1d 100644 --- a/packages/ludic.ui/attr.ludic +++ b/packages/ludic.ui/attr.ludic @@ -16,7 +16,7 @@ function el_apply(ui_st: mut UiState, n: UiNode, key: string, v0: Val) -> bool { return true } let v = cs_vars_in(ui_st, n, v0) - return el_size(ui_st, n, k, v) or el_box(ui_st, n, k, v) or el_flex(n, k, v) or el_look(ui_st, n, k, v) or el_place_prop(ui_st, n, k, v) or el_edge(ui_st, n, k, v) or el_more(ui_st, n, k, v) + return el_size(ui_st, n, k, v) or el_box(ui_st, n, k, v) or el_flex(ui_st, n, k, v) or el_look(ui_st, n, k, v) or el_place_prop(ui_st, n, k, v) or el_edge(ui_st, n, k, v) or el_more(ui_st, n, k, v) } function at_alias(key: string) -> string { # the CSS name to the short one; literals, so asking allocates nothing (asked per rule per element) @@ -47,12 +47,12 @@ function el_size(ui_st: mut UiState, n: UiNode, key: string, v: Val) -> bool { if key == "w" or key == "h" { el_dim(ui_st, n, key == "w", v) } else if key == "min-w" { n.min_w = el_len(ui_st, v) } else if key == "max-w" { n.max_w = el_len(ui_st, v) } else if key == "min-h" { n.min_h = el_len(ui_st, v) } else if key == "max-h" { n.max_h = el_len(ui_st, v) } else if key == "gap" { n.gap = el_len(ui_st, v) } else { return false } return true } -function el_flex(n: UiNode, key: string, v: Val) -> bool { +function el_flex(ui_st: mut UiState, n: UiNode, key: string, v: Val) -> bool { let s = vl_text(v) if key == "dir" { n.dir = UI_COL if s == "row" { n.dir = UI_ROW } - } else if key == "grow" { n.grow = el_num(s) } else if key == "flex" { el_flex_short(n, s) } else if key == "wrap" { n.wrap = s == "wrap" or (vl_truthy(v) and s != "false" and s != "nowrap") } else if key == "align" { n.align = el_place(v) } else if key == "self" { n.self = el_place(v) } else if key == "justify" { n.justify = el_place(v) } else if key == "talign" { n.talign = el_place(v) } else if key == "display" { n.hidden = s == "none" } else { return false } + } else if key == "grow" { n.grow = el_num(s) } else if key == "flex" { el_flex_short(ui_st, n, s) } else if key == "wrap" { n.wrap = s == "wrap" or (vl_truthy(v) and s != "false" and s != "nowrap") } else if key == "align" { n.align = el_place(v) } else if key == "self" { n.self = el_place(v) } else if key == "justify" { n.justify = el_place(v) } else if key == "talign" { n.talign = el_place(v) } else if key == "display" { n.hidden = s == "none" } else { return false } return true } function el_look(ui_st: mut UiState, n: UiNode, key: string, v: Val) -> bool { @@ -76,7 +76,7 @@ function el_look(ui_st: mut UiState, n: UiNode, key: string, v: Val) -> bool { } # border: 1 #ffcc00, or 1px solid accent function el_border(ui_st: mut UiState, n: UiNode, s: string) -> void { - let parts = lss_split(s, 32) + let parts = mm_split(ui_st, s, 32) for i in 0 .. len(parts) { let p = parts[i] if len(p) > 0 and ((p[0] >= 48 and p[0] <= 57) or p[0] == 46) { el_sides_border(n, el_unit(ui_st, p)) } else if p == "none" { el_sides_border(n, 0.0) } else if len(p) > 0 and p != "solid" { diff --git a/packages/ludic.ui/attr_box.ludic b/packages/ludic.ui/attr_box.ludic index ef47a222..edc37eb1 100644 --- a/packages/ludic.ui/attr_box.ludic +++ b/packages/ludic.ui/attr_box.ludic @@ -18,20 +18,27 @@ function el_box(ui_st: mut UiState, n: UiNode, key: string, v: Val) -> bool { } # top right bottom left out of 1 to 4 lengths function el_sides(ui_st: mut UiState, v: Val) -> void { - let parts = new []float - if vl_num(v) { push(parts, el_px(ui_st, Value.as_float(v))) } else { - let words = el_words(vl_text(v)) + var n = 0 + if vl_num(v) { + ui_st.el_s0 = el_px(ui_st, Value.as_float(v)) + n = 1 + } else { + let words = mm_words(ui_st, vl_text(v)) for i in 0 .. len(words) { - if len(words[i]) > 0 { push(parts, el_word_len(ui_st, words[i])) } + if len(words[i]) > 0 and n < 4 { + el_side_set(ui_st, n, el_word_len(ui_st, words[i])) + n += 1 + } } } - while len(parts) < 4 { - if len(parts) == 0 { push(parts, 0.0) } else if len(parts) == 1 { push(parts, parts[0]) } else if len(parts) == 2 { push(parts, parts[0]) } else { push(parts, parts[1]) } - } - ui_st.el_s0 = parts[0] - ui_st.el_s1 = parts[1] - ui_st.el_s2 = parts[2] - ui_st.el_s3 = parts[3] + if n == 0 { ui_st.el_s0 = 0.0 } + if n < 2 { ui_st.el_s1 = ui_st.el_s0 } + if n < 3 { ui_st.el_s2 = ui_st.el_s0 } + if n < 4 { ui_st.el_s3 = ui_st.el_s1 } +} +# CSS's one to four sides, top right bottom left, without a list made for them +function el_side_set(ui_st: mut UiState, i: int, v: float) -> void { + if i == 0 { ui_st.el_s0 = v } else if i == 1 { ui_st.el_s1 = v } else if i == 2 { ui_st.el_s2 = v } else { ui_st.el_s3 = v } } # a length: a number, 10px, 1.5em, 2rem, 50vw, calc(...), fill, fit or auto (a percentage is el_pct's) function el_len(ui_st: mut UiState, v: Val) -> float { diff --git a/packages/ludic.ui/attr_edge.ludic b/packages/ludic.ui/attr_edge.ludic index 1912fee7..51e4e09b 100644 --- a/packages/ludic.ui/attr_edge.ludic +++ b/packages/ludic.ui/attr_edge.ludic @@ -5,10 +5,10 @@ function el_edge(ui_st: mut UiState, n: UiNode, key: string, v: Val) -> bool { n.outline_c = ui_color(ui_st, s) n.outline_a = ui_st.cl_alpha } else if key == "scrollbar-color" { - let parts = lss_split(s, 32) + let parts = mm_split(ui_st, s, 32) if len(parts) > 0 { n.bar_c = ui_color(ui_st, parts[0]) } if len(parts) > 1 { n.bar_track = ui_color(ui_st, parts[1]) } - } else if key == "background-image" and gr_is(tpl_words(s)) { nx(n).grad = gr_parse(ui_st, s) } else if key == "background-image" { n.bg_img = el_url(s) } else if key == "border-image" { el_border_image(ui_st, n, s) } else if key == "box-shadow" { el_shadow(ui_st, n, s) } else if key == "animation" { el_animation(n, s) } else if key == "transition" { n.tr_dur = el_secs(s) } else { return false } + } else if key == "background-image" and gr_is(tpl_words(s)) { nx(n).grad = gr_parse(ui_st, s) } else if key == "background-image" { n.bg_img = el_url(s) } else if key == "border-image" { el_border_image(ui_st, n, s) } else if key == "box-shadow" { el_shadow(ui_st, n, s) } else if key == "animation" { el_animation(ui_st, n, s) } else if key == "transition" { n.tr_dur = el_secs(s) } else { return false } return true } # url(path) or url("path") -> path @@ -20,11 +20,11 @@ function el_url(s: string) -> string { return t } # border-image: url(chip.png) 14 / 12px - the source's corner size, then how wide they are drawn -function el_border_image(ui_st: UiState, n: UiNode, s: string) -> void { +function el_border_image(ui_st: mut UiState, n: UiNode, s: string) -> void { var close = 0 while close < len(s) and s[close] != 41 { close += 1 } n.bi_src = el_url(s[0..Math.min(close + 1, len(s))]) - let rest = lss_split(s[Math.min(close + 1, len(s))..len(s)], 47) + let rest = mm_split(ui_st, s[Math.min(close + 1, len(s))..len(s)], 47) n.bi_slice = el_num(tpl_words(rest[0])) n.bi_width = el_px(ui_st, n.bi_slice) if len(rest) > 1 { n.bi_width = el_unit(ui_st, tpl_words(rest[1])) } @@ -35,7 +35,7 @@ function el_shadow(ui_st: mut UiState, n: UiNode, s: string) -> void { n.sh_c = -2 return } - let parts = lss_split(s, 32) + let parts = mm_split(ui_st, s, 32) var nums = 0 var col = "" for i in 0 .. len(parts) { @@ -53,7 +53,7 @@ function el_shadow(ui_st: mut UiState, n: UiNode, s: string) -> void { } # outline: 2px solid #ffcc00, or none function el_outline(ui_st: mut UiState, n: UiNode, s: string) -> void { - let parts = lss_split(s, 32) + let parts = mm_split(ui_st, s, 32) n.outline_w = 0.0 for i in 0 .. len(parts) { let p = parts[i] @@ -64,8 +64,8 @@ function el_outline(ui_st: mut UiState, n: UiNode, s: string) -> void { } } # animation: fade 0.25s infinite alternate -function el_animation(n: UiNode, s: string) -> void { - let parts = lss_split(s, 32) +function el_animation(ui_st: mut UiState, n: UiNode, s: string) -> void { + let parts = mm_split(ui_st, s, 32) n.anim = "" for i in 0 .. len(parts) { let p = parts[i] diff --git a/packages/ludic.ui/attr_fit.ludic b/packages/ludic.ui/attr_fit.ludic index fa083941..b54c1834 100644 --- a/packages/ludic.ui/attr_fit.ludic +++ b/packages/ludic.ui/attr_fit.ludic @@ -2,7 +2,7 @@ # for pictures and natives, zoom (zoom.ludic), and a list split at its top-level commas function el_fit_props(ui_st: mut UiState, n: UiNode, key: string, s: string) -> bool { if key == "aspect-ratio" { - let parts = lss_split(s, 47) + let parts = mm_split(ui_st, s, 47) var r = el_num(tpl_words(parts[0])) if len(parts) > 1 and el_num(tpl_words(parts[1])) > 0.0 { r = r / el_num(tpl_words(parts[1])) } if tpl_words(s) == "auto" { r = 0.0 } diff --git a/packages/ludic.ui/attr_more.ludic b/packages/ludic.ui/attr_more.ludic index 426b78b0..df55e8bb 100644 --- a/packages/ludic.ui/attr_more.ludic +++ b/packages/ludic.ui/attr_more.ludic @@ -40,8 +40,8 @@ function el_calc_len(ui_st: mut UiState, s: string) -> float { return ui_st.ca_px } # flex: 1 | flex: 1 0 | flex: 2 1 auto | flex: none - the grow, then the shrink -function el_flex_short(n: UiNode, s: string) -> void { - let parts = el_words(s) +function el_flex_short(ui_st: mut UiState, n: UiNode, s: string) -> void { + let parts = mm_words(ui_st, s) if s == "none" { n.grow = 0.0 nx(n).shrink = 0.0 @@ -72,7 +72,7 @@ function el_text_shadow(ui_st: mut UiState, n: UiNode, s: string) -> void { x.tsh_set = true x.tsh_c = -2 if tpl_words(s) == "none" { return } - let parts = el_words(s) + let parts = mm_words(ui_st, s) var nums = 0 var col = "" for i in 0 .. len(parts) { diff --git a/packages/ludic.ui/backend.ludic b/packages/ludic.ui/backend.ludic index dbbba037..74fe587d 100644 --- a/packages/ludic.ui/backend.ludic +++ b/packages/ludic.ui/backend.ludic @@ -34,6 +34,8 @@ function ui_default_backend() -> UiBackend { export state UiState { pl_pools: []UiPool = new []UiPool # pool.ludic: each screen's nodes and envs, used again pl_cur: UiPool = null + mm: UiMemo = null # memo.ludic: splits, gradients and keys by their text + mm_ints: []string = null an_frames: []UiKeyframes = new []UiKeyframes an_keys: []string = new []string an_start: []float = new []float diff --git a/packages/ludic.ui/build.ludic b/packages/ludic.ui/build.ludic index 0e76d38b..7ff8d45c 100644 --- a/packages/ludic.ui/build.ludic +++ b/packages/ludic.ui/build.ludic @@ -8,7 +8,7 @@ function bd_kids(ui_st: mut UiState, kids: []UiTpl, e0: UiEnv, key: string, out: for i in 0 .. len(kids) { let k = kids[i] ui_st.ui_at = k.where - let ck = `{key}/{i}` + let ck = mm_join(ui_st, key, "/", mm_int(ui_st, i)) if k.tag == "state" or k.tag == "style" { continue } if k.tag == "let" { e = bd_let(ui_st, k, e) @@ -50,9 +50,9 @@ function bd_each(ui_st: mut UiState, k: UiTpl, e: UiEnv, key: string, out: []UiN let le = env_new(ui_st, e) env_bind(le, as_name, Value.at(list, j)) env_bind(le, at_name, Value.int(j)) - var id = string(j) + var id = mm_int(ui_st, j) if by != null { id = ui_eval_text(ui_st, by, le) } - bd_kids(ui_st, k.kids, le, `{key}#{id}`, out) + bd_kids(ui_st, k.kids, le, mm_join(ui_st, key, "#", id), out) } } # is what the component's user put inside it; their