106 lines
4 KiB
Text
106 lines
4 KiB
Text
# native.ludic - elements the host draws itself: ui_native("keybind", measure, draw) makes
|
|
# <keybind> a tag like any other, laid out and styled by the template, drawn by the host. A native
|
|
# says what happened with ui_fire(n, "change", value): the element's on-change runs once the frame
|
|
# is drawn, with `event.value` (and `event.name`) to read.
|
|
export property UiNative {
|
|
tag: string = ""
|
|
measure: fn(UiNode, float) -> void = null # the content's size into n.mw, n.mh; avail is the room
|
|
draw: fn(UiNode) -> void = null
|
|
input: fn(UiNode, UiPointer) -> bool = null # the pointer on it (pointer_events.ludic)
|
|
}
|
|
export function ui_native(ui_st: mut UiState, tag: string, measure: fn(UiNode, float) -> void, draw: fn(UiNode) -> void) -> void {
|
|
let nv = new UiNative
|
|
nv.tag = tag
|
|
nv.measure = measure
|
|
nv.draw = draw
|
|
for i in 0 .. len(ui_st.nt_list) {
|
|
if ui_st.nt_list[i].tag == tag {
|
|
nv.input = ui_st.nt_list[i].input
|
|
ui_st.nt_list[i] = nv
|
|
return
|
|
}
|
|
}
|
|
push(ui_st.nt_list, nv)
|
|
}
|
|
# the pointer on a native: its presses, moves, drags, releases and the wheel, while it is over it or
|
|
# has it captured; answering false to a pointerdown leaves the pointer free
|
|
export function ui_native_input(ui_st: mut UiState, tag: string, f: fn(UiNode, UiPointer) -> bool) -> void {
|
|
let nv = nt_find(ui_st, tag)
|
|
if nv == null {
|
|
@alloc_ok("only when a template is wrong: a broken screen, never a working one")
|
|
ui_err(ui_st, `ui_native_input: there is no native <{tag}> - ui_native it first`)
|
|
return
|
|
}
|
|
nv.input = f
|
|
}
|
|
function nt_find(ui_st: UiState, tag: string) -> UiNative {
|
|
for i in 0 .. len(ui_st.nt_list) {
|
|
if ui_st.nt_list[i].tag == tag { return ui_st.nt_list[i] }
|
|
}
|
|
return null
|
|
}
|
|
function nt_fired_clear(ui_st: mut UiState) -> void {
|
|
List.clear(ui_st.nt_q_nodes)
|
|
List.clear(ui_st.nt_q_names)
|
|
List.clear(ui_st.nt_q_vals)
|
|
}
|
|
export function ui_fire(ui_st: mut UiState, n: UiNode, name: string, value: Val) -> void {
|
|
ui_kept(ui_st.nt_q_nodes, n)
|
|
ui_kept(ui_st.nt_q_names, name)
|
|
ui_kept(ui_st.nt_q_vals, value)
|
|
}
|
|
function nt_fired_run(ui_st: mut UiState) -> void {
|
|
let nodes = ui_st.nt_q_nodes # run from these while what they fire goes to the spares
|
|
let names = ui_st.nt_q_names
|
|
let vals = ui_st.nt_q_vals
|
|
ui_st.nt_q_nodes = ui_st.nt_sp_nodes
|
|
ui_st.nt_q_names = ui_st.nt_sp_names
|
|
ui_st.nt_q_vals = ui_st.nt_sp_vals
|
|
nt_fired_clear(ui_st)
|
|
for i in 0 .. len(nodes) { nt_run(ui_st, nodes[i], names[i], vals[i]) }
|
|
ui_st.nt_sp_nodes = nodes
|
|
ui_st.nt_sp_names = names
|
|
ui_st.nt_sp_vals = vals
|
|
}
|
|
# the element's on-<name>, with `event` bound to what happened
|
|
function nt_run(ui_st: mut UiState, n: UiNode, name: string, value: Val) -> void {
|
|
if n.on_names == null or not n.enabled { return }
|
|
for i in 0 .. len(n.on_names) {
|
|
if n.on_names[i] == name {
|
|
var ev = Value.object()
|
|
if (lk_in(PE_NAMES, name) or name == "hold") and Value.kind(value) == 6 { ev = value }
|
|
Value.put(ev, "name", Value.str(name))
|
|
Value.put(ev, "value", value)
|
|
let e = env_new(ui_st, n.env)
|
|
env_bind(e, "event", ev)
|
|
act_run(ui_st, n.on_acts[i], e)
|
|
}
|
|
}
|
|
}
|
|
# an attribute of an element, as the template gave it (null when it has none) - for a native
|
|
export function ui_attr(n: UiNode, key: string) -> Val {
|
|
if n.akeys == null { return Value.null() }
|
|
for i in 0 .. len(n.akeys) {
|
|
if n.akeys[i] == key { return n.vals[i] }
|
|
}
|
|
return Value.null()
|
|
}
|
|
export function ui_attr_text(n: UiNode, key: string) -> string {
|
|
if n.akeys == null { return "" }
|
|
for i in 0 .. len(n.akeys) {
|
|
if n.akeys[i] == key { return vl_text(n.vals[i]) }
|
|
}
|
|
return ""
|
|
}
|
|
# a boolean attribute: present with no value is true, as HTML's are (<button autofocus>)
|
|
export function ui_attr_on(n: UiNode, key: string) -> bool {
|
|
if n.akeys == null { return false }
|
|
for i in 0 .. len(n.akeys) {
|
|
if n.akeys[i] == key { return el_flag(n.vals[i]) }
|
|
}
|
|
return false
|
|
}
|
|
function el_flag(v: Val) -> bool {
|
|
if Value.kind(v) == 4 and Value.as_str(v) == "" { return true }
|
|
return vl_truthy(v) and vl_text(v) != "false"
|
|
}
|