# 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 }