ludic/packages/ludic.ui/scroll_bar.ludic

57 lines
2.8 KiB
Text

# scroll_bar.ludic - a scroll box's bar: .ui-scrollbar, the track down its right edge, and its
# .ui-thumb, styled by the default sheet or a theme as the box's own parts. A press on the thumb holds
# it where it was taken; a press on the track jumps the thumb's middle to the pointer and holds it there.
# the bar's parts, styled as descendants of the box, and where they are at this offset
function sb_geo(ui_st: mut UiState, n: UiNode, off: float, room: float, most: float) -> void {
let bar = ct_part(ui_st, n, "ui-scrollbar", "")
bar.tag = "div"
bar.parent = n
push(bar.children, ct_part(ui_st, n, "ui-thumb", ""))
cs_tree(ui_st, bar)
ui_st.sb_bar = bar
ui_st.sb_w = ui_px(ui_st, 6.0)
if bar.w >= 0.0 { ui_st.sb_w = bar.w }
ui_st.sb_x = n.x + n.cw - ui_st.sb_w - bar.mr
var least = ui_px(ui_st, 24.0)
if len(bar.children) > 0 and bar.children[0].min_h > 0.0 { least = bar.children[0].min_h }
ui_st.sb_th = Math.min(Math.max(n.ch * room / (room + most), least), n.ch)
ui_st.sb_ty = n.y
if most > 0.0 { ui_st.sb_ty = n.y + (n.ch - ui_st.sb_th) * Math.clamp(off, 0.0, most) / most }
}
# the pointer on the bar: taken on a press over it, moved while held, let go on release
function sb_input(ui_st: mut UiState, n: UiNode, off: float, room: float, most: float) -> float {
let i = ui_st.in_now
if most <= 0.0 or room <= 0.0 { return off }
if i.down and not ui_st.in_was_down and ui_st.sc_drag == "" {
sb_geo(ui_st, n, off, room, most)
let reach = Math.min(ui_st.sb_x, n.x + n.cw - ui_px(ui_st, 14.0))
let over = i.x >= reach and i.y >= n.y and i.x < n.x + n.cw and i.y < n.y + n.ch
if over and not ui_st.sb_bar.hidden {
ui_st.sc_drag = n.key
ui_st.sc_grab = ui_st.sb_th / 2.0
if i.y >= ui_st.sb_ty and i.y < ui_st.sb_ty + ui_st.sb_th { ui_st.sc_grab = i.y - ui_st.sb_ty }
}
}
if ui_st.sc_drag != n.key { return off }
sb_geo(ui_st, n, off, room, most)
let span = n.ch - ui_st.sb_th
if span <= 0.0 { return off }
return (i.y - ui_st.sc_grab - n.y) / span * most
}
# the track, then the thumb over it; scrollbar-color on the box wins over the parts' backgrounds
function sc_bar(ui_st: mut UiState, n: UiNode) -> void {
let room = n.ch - ly_vin(n)
let most = n.content_h - ly_vin(n) - room
if most <= 0.0 or ui_st.ui_be.rect == null { return }
sb_geo(ui_st, n, n.scroll_y, room, most)
let bar = ui_st.sb_bar
if bar.hidden { return }
var track = bar.bg
if n.bar_track != -2 { track = n.bar_track }
if track >= 0 { fr_box(ui_st, ui_st.sb_x, n.y, ui_st.sb_w, n.ch, bar.radius, track, bar.bg_a * ui_st.fr_ga) }
if len(bar.children) == 0 { return }
let t = bar.children[0]
var thumb = t.bg
if n.bar_c >= 0 { thumb = n.bar_c }
if thumb >= 0 { fr_box(ui_st, ui_st.sb_x, ui_st.sb_ty, ui_st.sb_w, ui_st.sb_th, t.radius, thumb, t.bg_a * ui_st.fr_ga) }
}