Merge commit '181d317' into lang/foundations
This commit is contained in:
commit
41ad5d1e9b
8 changed files with 140 additions and 18 deletions
|
|
@ -53,6 +53,8 @@ export state UiState {
|
|||
nt_ev_at: int = 0
|
||||
nt_nums: []Val = nt_nums_new() # fired.ludic: the numbers a scroll or a slider reports, a ring
|
||||
nt_num_at: int = 0
|
||||
ct_clamp_n: []UiNode = new []UiNode # controls_opts.ludic: selects whose value a build clamped
|
||||
ct_clamp_i: []int = new []int
|
||||
hd_ev: Val = hd_ev_new() # hold.ludic: the held control's event, filled in place
|
||||
cv_texts: []string = new []string # units_pieces.ludic: a value's var() pieces, kept
|
||||
tx_pieces: [][]string = new [][]string # eval_text.ludic: a text's pieces, a list a depth
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ function ct_activate(ui_st: mut UiState, n: UiNode) -> void {
|
|||
function ct_step(ui_st: mut UiState, n: UiNode, d: int) -> void {
|
||||
let t = ct_type(n)
|
||||
if t == "select" and n.opts != null and len(n.opts) > 0 {
|
||||
let at = (ct_option_at(n, n.opts) + d + len(n.opts)) % len(n.opts)
|
||||
let ov = ui_attr(n.opts[at], "value")
|
||||
if Value.kind(ov) == 0 { ct_change(ui_st, n, Value.int(at)) } else { ct_change(ui_st, n, ov) }
|
||||
let from = ct_option_at(n, n.opts)
|
||||
let at = ct_opt_step(n.opts, from, d) # past a disabled option
|
||||
if at != from { ct_opt_pick(ui_st, n, n.opts, at) }
|
||||
}
|
||||
if t == "number" { ct_num_step(ui_st, n, d) }
|
||||
if t == "range" {
|
||||
|
|
|
|||
|
|
@ -67,21 +67,6 @@ function ct_build_range(ui_st: mut UiState, n: UiNode) -> void {
|
|||
ui_kept(n.children, track)
|
||||
ui_kept(n.children, ct_part(ui_st, n, "ui-value", ct_value_shown(ui_st, n)))
|
||||
}
|
||||
function ct_build_select(ui_st: mut UiState, n: UiNode) -> void {
|
||||
@alloc_ok("once per pooled node: its list is kept and cleared")
|
||||
if n.opts == null { n.opts = new []UiNode } # its options moved to a list the node keeps, not a new one
|
||||
let opts = n.opts
|
||||
List.clear(opts)
|
||||
for i in 0 .. len(n.children) { ui_kept(opts, n.children[i]) }
|
||||
List.clear(n.children)
|
||||
ct_label(ui_st, n)
|
||||
var shown = ""
|
||||
let at = ct_option_at(n, opts)
|
||||
if at >= 0 { shown = opts[at].text }
|
||||
ui_kept(n.children, ct_part(ui_st, n, "ui-prev", "<"))
|
||||
ui_kept(n.children, ct_part(ui_st, n, "ui-value", shown))
|
||||
ui_kept(n.children, ct_part(ui_st, n, "ui-next", ">"))
|
||||
}
|
||||
# which option the select's value names: an option's value="...", else its place
|
||||
function ct_option_at(n: UiNode, opts: []UiNode) -> int {
|
||||
let nv = ui_attr(n, "value")
|
||||
|
|
|
|||
76
packages/ludic.ui/controls_opts.ludic
Normal file
76
packages/ludic.ui/controls_opts.ludic
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# controls_opts.ludic - <option disabled="{...}">: a select steps past a disabled option (arrows, a
|
||||
# press, the pad), a value naming one is shown and set as the nearest enabled option, and the arrow
|
||||
# whose next option is disabled is drawn disabled - the options that way are off (a host's cap)
|
||||
function ct_opt_on(opts: []UiNode, i: int) -> bool { return i >= 0 and i < len(opts) and opts[i].enabled }
|
||||
|
||||
# from `at` d steps at a time, wrapping, to the first enabled option; `at` itself when none is
|
||||
function ct_opt_step(opts: []UiNode, at: int, d: int) -> int {
|
||||
let n = len(opts)
|
||||
var i = at
|
||||
for k in 0 .. n {
|
||||
i = (i + d + n) % n
|
||||
if opts[i].enabled { return i }
|
||||
}
|
||||
return at
|
||||
}
|
||||
|
||||
# the enabled option nearest `at` (the lower of two as near); -1 when none is
|
||||
function ct_opt_nearest(opts: []UiNode, at: int) -> int {
|
||||
if ct_opt_on(opts, at) { return at }
|
||||
for r in 1 .. len(opts) {
|
||||
if ct_opt_on(opts, at - r) { return at - r }
|
||||
if ct_opt_on(opts, at + r) { return at + r }
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
# a select's value on a disabled option: the nearest enabled one is what it shows, and is set
|
||||
# (set once the build is done: an event fired while the tree is built is cleared with the frame's)
|
||||
function ct_opt_clamp(ui_st: mut UiState, n: UiNode, opts: []UiNode, at: int) -> int {
|
||||
if at < 0 or ct_opt_on(opts, at) { return at }
|
||||
let to = ct_opt_nearest(opts, at)
|
||||
if to >= 0 {
|
||||
ui_kept(ui_st.ct_clamp_n, n)
|
||||
ui_kept(ui_st.ct_clamp_i, to)
|
||||
}
|
||||
return to
|
||||
}
|
||||
# the clamps a build found, set now that the frame's events are cleared; stale ones are dropped
|
||||
function ct_opt_flush(ui_st: mut UiState) -> void {
|
||||
for i in 0 .. len(ui_st.ct_clamp_n) {
|
||||
let n = ui_st.ct_clamp_n[i]
|
||||
if n.opts != null and ui_st.ct_clamp_i[i] < len(n.opts) { ct_opt_pick(ui_st, n, n.opts, ui_st.ct_clamp_i[i]) }
|
||||
}
|
||||
ct_opt_forget(ui_st)
|
||||
}
|
||||
function ct_opt_forget(ui_st: mut UiState) -> void {
|
||||
List.clear(ui_st.ct_clamp_n)
|
||||
List.clear(ui_st.ct_clamp_i)
|
||||
}
|
||||
function ct_opt_pick(ui_st: mut UiState, n: UiNode, opts: []UiNode, at: int) -> void {
|
||||
let ov = ui_attr(opts[at], "value")
|
||||
if Value.kind(ov) == 0 { ct_change(ui_st, n, Value.int(at)) } else { ct_change(ui_st, n, ov) }
|
||||
}
|
||||
|
||||
# a select: its label, < and >, and the option its value names between them (<option>s kept aside)
|
||||
function ct_build_select(ui_st: mut UiState, n: UiNode) -> void {
|
||||
@alloc_ok("once per pooled node: its list is kept and cleared")
|
||||
if n.opts == null { n.opts = new []UiNode } # its options moved to a list the node keeps, not a new one
|
||||
let opts = n.opts
|
||||
List.clear(opts)
|
||||
for i in 0 .. len(n.children) { ui_kept(opts, n.children[i]) }
|
||||
List.clear(n.children)
|
||||
ct_label(ui_st, n)
|
||||
var shown = ""
|
||||
let at = ct_opt_clamp(ui_st, n, opts, ct_option_at(n, opts))
|
||||
if at >= 0 { shown = opts[at].text }
|
||||
let prev = ct_part(ui_st, n, "ui-prev", "<")
|
||||
let next = ct_part(ui_st, n, "ui-next", ">")
|
||||
if at >= 0 and len(opts) > 1 {
|
||||
prev.enabled = ct_opt_on(opts, (at - 1 + len(opts)) % len(opts))
|
||||
next.enabled = ct_opt_on(opts, (at + 1) % len(opts))
|
||||
}
|
||||
ui_kept(n.children, prev)
|
||||
ui_kept(n.children, ct_part(ui_st, n, "ui-value", shown))
|
||||
ui_kept(n.children, next)
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
export function ui_show(ui_st: mut UiState, screen: string, view: UiView, x: float, y: float, w: float, h: float) -> void {
|
||||
in_read(ui_st)
|
||||
ct_opt_forget(ui_st) # a clamp found by a build this frame did not show
|
||||
dv_before(ui_st)
|
||||
ui_st.an_frame += 1
|
||||
ui_viewport(ui_st, w, h)
|
||||
|
|
@ -12,6 +13,7 @@ export function ui_show(ui_st: mut UiState, screen: string, view: UiView, x: flo
|
|||
if root == null { return }
|
||||
ui_place(ui_st, root, x, y, w, h)
|
||||
nt_fired_clear(ui_st)
|
||||
ct_opt_flush(ui_st) # a select's value on a disabled option, set now
|
||||
sc_undo(root)
|
||||
sc_update(ui_st, root)
|
||||
fr_pointer(ui_st, root)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import "fired.ludic"
|
|||
import "native_room.ludic"
|
||||
import "controls.ludic"
|
||||
import "controls_build.ludic"
|
||||
import "controls_opts.ludic"
|
||||
import "controls_parts.ludic"
|
||||
import "controls_key.ludic"
|
||||
import "controls_key_mouse.ludic"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue