ludic/packages/ludic.ui/tooltip.ludic

75 lines
2.6 KiB
Text

# tooltip.ludic - an element's title="..." shown beside the pointer once it has rested on it for half
# a second (or under it, when the keyboard's focus has), in a box styled by .ui-tooltip; a title of
# several lines (a newline, or \n) is one .ui-tooltip-text a line
function tt_track(ui_st: mut UiState, root: UiNode, x: float, y: float) -> void {
var scope = pp_top(root)
if scope == null { scope = root }
var n = tt_under(scope, x, y)
var px = x
var py = y
let k = tt_focused(ui_st, scope, x, y)
if k != null {
n = k
px = k.x
py = k.y + k.ch - ui_px(ui_st, 14.0)
}
if n == null {
ui_st.tt_key = ""
return
}
let title = ui_attr_text(n, "title")
if n.key != ui_st.tt_key {
ui_st.tt_key = n.key
ui_st.tt_since = an_now(ui_st)
ui_st.tt_src = null
}
if ui_st.tt_src == null or title != ui_st.tt_src { # translated when the element or its title changes, not a frame
ui_st.tt_src = title
ui_st.tt_text = tt_translate(ui_st, n, title)
}
ui_st.tt_x = px
ui_st.tt_y = py
}
# the deepest element under the point that has a title
function tt_under(n: UiNode, x: float, y: float) -> UiNode {
if x < n.x or y < n.y or x >= n.x + n.cw or y >= n.y + n.ch { return null }
var i = len(n.children) - 1
while i >= 0 {
let t = tt_under(n.children[i], x, y)
if t != null { return t }
i -= 1
}
if n.akeys != null and ui_attr_text(n, "title") != "" { return n }
return null
}
function tt_draw(ui_st: mut UiState, root: UiNode) -> void {
if ui_st.tt_key == "" or ui_st.tt_text == "" or an_now(ui_st) - ui_st.tt_since < 0.5 { return }
let n = ct_part(ui_st, root, "ui-tooltip", "")
n.tag = "div"
n.parent = root
let lines = tt_lines(ui_st, ui_st.tt_text)
for i in 0 .. len(lines) { ui_kept(n.children, ct_part(ui_st, root, "ui-tooltip-text", lines[i])) }
cs_tree(ui_st, n)
ly_measure(ui_st, n, ui_st.ly_vp_w * 0.4, ui_px(ui_st, 16.0), root.rfg)
let x = Math.min(ui_st.tt_x + ui_px(ui_st, 16.0), ui_st.ly_vp_x + ui_st.ly_vp_w - n.mw)
let y = Math.min(ui_st.tt_y + ui_px(ui_st, 20.0), ui_st.ly_vp_y + ui_st.ly_vp_h - n.mh)
ly_place(ui_st, n, x, y, n.mw, n.mh)
fr_draw(ui_st, n)
}
# a title's lines: apart at a newline, or at a written \n (which an attribute cannot hold otherwise)
@alloc_ok("a memo miss: once per title (memo_more.ludic), bounded by MM_CAP")
function tt_lines_new(s: string) -> []string {
let out = new []string
var at = 0
var i = 0
while i < len(s) {
if s[i] == 10 or (s[i] == 92 and i + 1 < len(s) and s[i + 1] == 110) {
push(out, s[at..i])
if s[i] == 92 { i += 1 }
at = i + 1
}
i += 1
}
push(out, s[at..len(s)])
return out
}