initial script after splitting up text-zoom

akkartik
Dec 31, 2023, 11:49 PM
GVX7YSQYURPWFSUWVUAORZJTQBJURWWNBNUGEZYFAUMX3X5LSACQC

Dependencies

Change contents

  • file addition: screens (d--r------)
    [2.2]
  • file addition: widgets (----------)
    [0.1]
    widgets = {}
    -- button to invoke add_editor
    table.insert(widgets, {
    draw = function()
    color(0, 0.6,0.6)
    rect('line', Safe_width-65, Menu_bottom+5, 30,30, 5)
    line(Safe_width-60, Menu_bottom+20, Safe_width-40, Menu_bottom+20)
    line(Safe_width-50, Menu_bottom+10, Safe_width-50, Menu_bottom+30)
    end,
    ispress = function(x2,y2)
    return x2 >= Safe_width-65 and y2 <= Menu_bottom+35
    end,
    press = add_editor,
    })
  • file addition: typographic-scale (----------)
    [0.1]
    typographic_scale = {6,7,8,9,10,12,14,16,18,21,24,28,32,36,42,48,55,63,73,84,96}
    for i,v in ipairs(typographic_scale) do
    typographic_scale[i] = v*4 end
    function higher_element(a,v)
    if v == a[#a] then return v
    else return a[array.find(a,v)+1] end
    end
    function lower_element(a,v)
    if v == a[1] then return v
    else return a[array.find(a,v)-1] end
    end
  • file addition: text-box (----------)
    [0.1]
    cursor = nil
    -- a single text box
    function add_editor()
    -- some variables shared by all the widgets in the text box
    local x,y, w,h = 50, Menu_bottom+10, 100, 100 -- surface coords
    local font_height = typographic_scale[6]
    local font = g.newFont(scale(font_height))
    local e = edit.initialize_state(vy(y), vy(y+h), vx(x), vx(x+w), font, scale(font_height), floor(scale(font_height)*1.3))
    --e.filename = 'example.txt'
    --load_from_disk(e)
    Text.redraw_all(e)
    -- core editor widget
    local r = {}
    r.draw = function()
    g.setFont(font)
    edit.draw(e, {r=0.5, g=0.5, b=0.5}, cursor ~= r)
    color(0.5,0.5,0.5)
    rect('line', e.left-5, e.top-5, e.width+5*2, (e.bottom+5)-(e.top-5))
    end
    r.ispress = function(x2,y2)
    return x2 >= e.left-5 and x2 <= e.right+5 and y2 >= e.top-5 and y2 <= e.bottom+5
    end
    r.press = function(x2,y2, b)
    cursor = r
    edit.mouse_press(e, x2,y2, b)
    end
    r.update = function(dt, x2,y2)
    if cursor == r then
    --edit.update(e, dt)
    elseif f then
    if s then
    e.font_height = scale(font_height)
    e.line_height = floor(e.font_height*1.3)
    font = g.newFont(e.font_height)
    end
    g.setFont(font)
    e.left, e.right = vx(x), vx(x+w)
    e.width = e.right - e.left
    e.top, e.bottom = vy(y), vy(y+h)
    Text.redraw_all(e)
    end
    end
    r.release = function(x2,y2, b) edit.mouse_release(e, x2,y2, b) end
    r.presschord = function(chord, key) edit.keychord_press(e, chord, key) end
    r.textinput = function(t) edit.text_input(e, t) end
    r.releasekey = function(key) edit.key_release(e, key) end
    --r.quit = function() edit.quit(e) end -- final save
    table.insert(widgets, r)
    -- move affordance
    local xoff, yoff
    table.insert(widgets, {
    draw = function()
    color(0.7,0.7,0.7)
    local x,y = e.left, e.top
    circle('fill', x+10,y-20, 15)
    end,
    ispress = function(x2,y2)
    return dist({x=e.left+10, y=e.top-20}, {x=x2, y=y2}) < 15
    end,
    press = function(x2,y2, b)
    xoff,yoff = x2-vx(x), y2-vy(y)
    end,
    update = function(dt, x2,y2)
    if not xoff then return end
    x,y = sx(x2-xoff), sy(y2-yoff)
    e.left, e.right = vx(x), vx(x+w)
    e.width = e.right - e.left
    e.top, e.bottom = vy(y), vy(y+h)
    Text.redraw_all(e)
    end,
    release = function(x2,y2, b)
    xoff,yoff = nil
    end,
    })
    -- resize affordances
    local adjw, adjh = {}, {}
    local width_adjustment, height_adjustment
    adjw.draw = function()
    color(0.5,0.5,0.5)
    for i=2,4 do -- i=1 is on the border
    line(e.right+5*i, e.top+5, e.right+5*i, e.bottom-5)
    end
    end
    adjh.draw = function()
    color(0.5,0.5,0.5)
    for i=2,4 do -- i=1 is on the border
    line(e.left+5, e.bottom+5*i, e.right-5, e.bottom+5*i)
    end
    end
    adjw.ispress = function(x2,y2)
    -- include a shadow to the right
    return x2 > e.right+5 and x2 <= e.right+5*5 and y2 >= e.top and y2 <= e.bottom
    end
    adjh.ispress = function(x2,y2)
    -- include a shadow below
    return x2 >= e.left and x2 <= e.right and y2 > e.bottom+5 and y2 <= e.bottom+5*5
    end
    adjw.press = function(x2,y2, b) width_adjustment = x2-e.right end
    adjh.press = function(x2,y2, b) height_adjustment = y2-e.bottom end
    adjw.release = function(x2,y2, b) width_adjustment = nil end
    adjh.release = function(x2,y2, b) height_adjustment = nil end
    adjw.update = function(dt, x2,y2)
    if not width_adjustment then return end
    e.right = x2-width_adjustment
    e.width = e.right - e.left
    w = iscale(e.width)
    g.setFont(font)
    Text.redraw_all(e)
    end
    adjh.update = function(dt, x2,y2)
    if not height_adjustment then return end
    e.bottom = y2-height_adjustment
    h = iscale(e.bottom-e.top)
    end
    table.insert(widgets, adjw)
    table.insert(widgets, adjh)
    -- font buttons
    local update_font = function(newf)
    if font_height == newf then return end
    font_height = newf
    e.font_height = scale(font_height)
    e.font = g.newFont(e.font_height)
    e.line_height = floor(e.font_height)*1.3
    Text.redraw_all(e)
    end
    table.insert(widgets, {
    draw = function()
    color(0.7,0.7,0.7)
    local x,y = e.left-35, e.top-5
    poly('fill', x+15,y, x,y+30, x+30,y+30)
    end,
    ispress = function(x2,y2)
    local x,y = e.left-35, e.top-5
    return x2 >= x and x2 <= x+30 and y2 >= y and y2 <= y+30
    end,
    press = function()
    update_font(higher_element(typographic_scale, font_height))
    end,
    })
    table.insert(widgets, {
    draw = function()
    color(0.7,0.7,0.7)
    local x,y = e.left-35, e.top+35
    poly('fill', x+15,y+30, x,y, x+30,y)
    end,
    ispress = function(x2,y2)
    local x,y = e.left-35, e.top+35
    return x2 >= x and x2 <= x+30 and y2 >= y and y2 <= y+30
    end,
    press = function()
    update_font(lower_element(typographic_scale, font_height))
    end,
    })
    end -- phew! done with add_editor
  • file addition: space (----------)
    [0.1]
    -- viewport
    v = {x=0, y=0, w=Safe_width, h=Safe_height, zoom=1.0}
    f,s = nil -- ids of first and second touches
    start, curr = {}, {} -- coords of touches
    initzoom = nil
    initpos = nil -- for panning
    function centroid(a, b)
    return{x=(a.x+b.x)/2, y=(a.y+b.y)/2}
    end
    function vx(sx) return scale(sx-v.x) end
    function vy(sy) return scale(sy-v.y) end
    function sx(vx) return v.x + iscale(vx) end
    function sy(vy) return v.y + iscale(vy) end
    function scale(d) return d*v.zoom end
    function iscale(d) return d/v.zoom end
    function dist(p1, p2)
    return ((p2.x-p1.x)^2 + (p2.y-p1.y)^2) ^ 0.5
    end
  • file addition: main (----------)
    [0.1]
    -- top-level handlers for dash's event loop
    -- main responsibilities:
    -- render widgets based on current viewport settings
    -- dispatch keyboard and touch events to appropriate widget
    -- pan viewport based on one-finger touch (from either mouse or touchscreen)
    -- adjust zoom based on two-finger touch (touchscreen only)
    function car.draw()
    for _,w in ipairs(widgets) do w.draw() end
    draw_hud()
    end
    function car.update(dt)
    for _,w in ipairs(widgets) do
    if w.update then
    w.update(dt, App.mouse_x(), App.mouse_y())
    end
    end
    end
    function car.mouse_press(x,y, b)
    skip_touch = nil
    cursor = nil
    for _,w in ipairs(widgets) do
    if w.ispress(x,y) then
    skip_touch = true
    return w.press(x,y, b)
    end
    end
    if f == nil then
    start.mouse = {x=x, y=y}
    curr.mouse = {x=x, y=y}
    f = 'mouse'
    initpos = {x=v.x, y=v.y}
    end
    end
    function car.touch_press(id, x,y, ...)
    if skip_touch then return end
    start[id] = {x=x, y=y}
    curr[id] = {x=x, y=y}
    if f == 'mouse' then
    f = id
    elseif f then
    s = id
    initzoom = v.zoom
    initpos = nil
    end
    end
    function car.mouse_move(x,y)
    if start.mouse then
    curr.mouse = {x=x, y=y}
    if not s then
    v.x = initpos.x + iscale(start.mouse.x - x)
    v.y = initpos.y + iscale(start.mouse.y - y)
    end end end
    function car.touch_move(id, x,y, ...)
    if start[id] then
    curr[id] = {x=x, y=y}
    if s then
    local oldzoom = v.zoom
    v.zoom = dist(curr[f], curr[s])/dist(start[f], start[s])*initzoom
    local c = centroid(curr[f], curr[s])
    v.x = v.x + c.x/oldzoom - c.x/v.zoom
    v.y = v.y + c.y/oldzoom - c.y/v.zoom
    end end end
    function car.mouse_release(x,y, b)
    for _,w in ipairs(widgets) do
    if w.release then w.release(x,y, b) end
    end
    f,s = nil
    start, curr = {}, {}
    skip_touch = nil
    initzoom = nil
    initpos = nil
    end
    function car.keychord_press(chord, key)
    if cursor then cursor.presschord(chord, key) end
    end
    function car.text_input(t)
    if cursor then cursor.textinput(t) end
    end
    function car.key_release(key)
    if cursor then cursor.releasekey(key) end
    end
    function car.quit()
    for name,w in pairs(widgets) do
    if w.quit then w.quit() end
    end
    end
  • file addition: hud (----------)
    [0.1]
    function draw_hud()
    color(0.5, 0.5, 0.5)
    for _,touch in ipairs(touches()) do
    if curr[touch] then
    circle('fill', curr[touch].x, curr[touch].y, 10)
    end
    end
    end