ludic/packages/ludic.ui/cascade_merge.ludic

56 lines
2.1 KiB
Text

# cascade_merge.ludic - a component's root is styled by its own sheet and by the sheet of every user
# that passed a class down to it, all at once: the rules that match, from all of them, ordered by
# specificity as one sheet's are. On a tie the user's rule wins (the outermost user's last), as a
# later rule does. Then `order`, which rearranges a flex box's children without touching the tree.
function cs_merged(ui_st: mut UiState, n: UiNode) -> void {
let rules = ui_st.cs_rules # kept and emptied: a merge runs once an element, never inside another
let envs = ui_st.cs_envs
let seen = ui_st.cs_seen
List.clear(rules)
List.clear(envs)
List.clear(seen)
if n.sheet != null { cs_gather(ui_st, n, n.sheet, n.env, rules, envs, seen) }
for i in 0 .. len(n.ups) {
if n.ups[i].sheet != null { cs_gather(ui_st, n, n.ups[i].sheet, n.ups[i].env, rules, envs, seen) }
}
for i in 0 .. len(rules) { cs_rule_in(ui_st, n, rules[i], envs[i]) }
}
# a sheet's matching rules into the list, each after every rule at most as specific (stable)
function cs_gather(ui_st: mut UiState, n: UiNode, sh: UiSheet, e: UiEnv, rules: []UiRule, envs: []UiEnv, seen: []UiSheet) -> void {
for i in 0 .. len(seen) {
if seen[i] == sh { return }
}
ui_kept(seen, sh)
for i in 0 .. len(sh.rules) {
let r = sh.rules[i]
if md_ok(ui_st, r) and sel_match(ui_st, r.sel, n) {
ui_kept(rules, r)
ui_kept(envs, e)
var j = len(rules) - 1
while j > 0 and rules[j - 1].spec > r.spec {
rules[j] = rules[j - 1]
envs[j] = envs[j - 1]
j -= 1
}
rules[j] = r
envs[j] = e
}
}
}
# CSS's order: the children placed by it, lowest first, the tree's order kept between equals
function cs_order(n: UiNode) -> void {
var any = false
for i in 0 .. len(n.children) {
if ly_order(n.children[i]) != 0 { any = true }
}
if not any { return }
for i in 1 .. len(n.children) {
let c = n.children[i]
var j = i
while j > 0 and ly_order(n.children[j - 1]) > ly_order(c) {
n.children[j] = n.children[j - 1]
j -= 1
}
n.children[j] = c
}
}