123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782 |
- return function(BOXUI)
- local utils = BOXUI.utils
- local int = utils.int
- local max = utils.max
- local clamp = utils.clamp
- local newbox = utils.newbox
- local setbox = utils.setbox
- local includes = utils.includesPoint
- local colorWhite = {1, 1, 1}
- local M = utils.newclass("container")
- M.template_theme = {
- sliderThickness = 20, sliderLengthMin = 50,
- sliderBack = {0, 0.5, 0},
- sliderForeActive = {1, 0, 0}, sliderFore = {0.75, 0, 0},
- borderThickness = 8,
- borderBack = {0, 0, 0.5},
- borderFore = {0, 1, 1},
-
- handleHeight = 20
- }
- -- AREAS
- local units = {}
- M.units = units
- -- Vertical Slider
- units.SLIDER_V = newbox("sliderVert" )
- units.SLIDER_V.drag = function(owner, x, y, dx, dy)
- local s = owner.boxes.sliderVert
- if s.dir ~= 0 then return end -- sliding
- local a_max = owner.viewYMax
- local a = owner.viewY
- local s_space = s.height - s.length
-
- a = clamp(a + int(dy * a_max / s_space), 0, a_max)
- if a ~= owner.viewY then
- owner.viewY = a
- s.pos = int((s_space * a) / a_max)
- owner.content:updateViewport(owner.viewX, owner.viewY, owner.viewW, owner.viewH)
- owner:redraw()
- end
- end
- units.SLIDER_V.update = function(owner, dt)
- local s = owner.boxes.sliderVert
- if s.dir == 0 then return end
- owner:slideTo( 0, s.dir, dt)
- end
- -- Horizontal Slider
- units.SLIDER_H = newbox("sliderHori")
- units.SLIDER_H.drag = function(owner, x, y, dx, dy)
- local s = owner.boxes.sliderHori
- if s.dir ~= 0 then return end -- sliding
- local a_max = owner.viewXMax
- local a = owner.viewX
- local s_space = s.width - s.length
-
- a = clamp(a + int(dx * a_max / s_space), 0, a_max)
- if a ~= owner.viewX then
- owner.viewX = a
- s.pos = int((s_space * a) / a_max)
- owner.content:updateViewport(owner.viewX, owner.viewY, owner.viewW, owner.viewH)
- end
- end
- units.SLIDER_H.update = function(owner, dt)
- local s = owner.boxes.sliderHori
- if s.dir == 0 then return end
- owner:slideTo(s.dir, 0, dt)
- end
- -- Handle
- units.HANDLE = newbox("handle")
- units.HANDLE.drag = function(owner, x, y, dx, dy)
- local handle = owner.boxes.handle
- local parent = owner.parent
- local pw, ph
- if parent then
- local box = (parent.boxes and parent.boxes.panel) or parent
- pw, ph = box.width, box.height
- else
- pw, ph = love.graphics.getDimensions()
- end
- owner.x = clamp(dx + owner.x, 0 - owner.width + 20, pw - 20)
- owner.y = clamp(dy + owner.y, 0, ph - handle.height)
- end
- -- Handle Buttons
- units.SHADE = newbox("shade" )
- units.SHADE.click = function(owner) owner:rollup() end
- units.EXPAND = newbox("expand")
- units.EXPAND.click = function(owner) owner:maximize() end
- units.CLOSE = newbox("close" )
- units.CLOSE.click = function(owner)
- local parent = owner.parent
- if parent and parent.remove then
- parent:remove(parent:find(owner))
- end
- end
- -- Scalers
- units.SCALE_N = newbox("scaleN" )
- units.SCALE_NE = newbox("scaleNE")
- units.SCALE_NW = newbox("scaleNW")
- units.SCALE_E = newbox("scaleE" )
- units.SCALE_W = newbox("scaleW" )
- units.SCALE_SE = newbox("scaleSE")
- units.SCALE_SW = newbox("scaleSW")
- units.SCALE_S = newbox("scaleS" )
- local scale = function(owner, x, y, dx, dy, xdir, ydir)
-
- owner.scaling = true
- local handle = owner.boxes.handle
- local parent = owner.parent
- local pw, ph
- local minw, minh = 150, 150
- local threshold = 20
- if parent then
- local box = (parent.boxes and parent.boxes.panel) or parent
- pw, ph = box.width, box.height
- else
- pw, ph = love.graphics.getDimensions()
- end
-
- local ownermax_x, ownermax_y = owner.x + owner.width, owner.y + owner.height
- -- fixme: this might be simplified
- if xdir < 0 then
- local x = clamp(owner.x + dx, 0, ownermax_x - minw)
- if x < pw - threshold then
- owner.width = clamp(owner.width - dx, minw, ownermax_x)
- owner.x = x
- end
- elseif xdir > 0 and ownermax_x + dx >= threshold then
- owner.width = clamp(owner.width + dx, minw, pw - owner.x)
- end
- if ydir < 0 then
- local y = clamp(owner.y + dy, 0, ownermax_y - minh)
- if y < ph - threshold then
- owner.height = clamp(owner.height - dy, minh, ownermax_y)
- owner.y = y
- end
- elseif ydir > 0 and ownermax_y + dy >= threshold then
- owner.height = clamp(owner.height + dy, minh, ph - owner.y)
- end
- end
- units.SCALE_N.drag = function(owner, x, y, dx, dy) scale(owner, x, y, dx, dy, 0, -1) end
- units.SCALE_NE.drag = function(owner, x, y, dx, dy) scale(owner, x, y, dx, dy, 1, -1) end
- units.SCALE_NW.drag = function(owner, x, y, dx, dy) scale(owner, x, y, dx, dy, -1, -1) end
- units.SCALE_E.drag = function(owner, x, y, dx, dy) scale(owner, x, y, dx, dy, 1, 0) end
- units.SCALE_W.drag = function(owner, x, y, dx, dy) scale(owner, x, y, dx, dy, -1, 0) end
- units.SCALE_SE.drag = function(owner, x, y, dx, dy) scale(owner, x, y, dx, dy, 1, 1) end
- units.SCALE_SW.drag = function(owner, x, y, dx, dy) scale(owner, x, y, dx, dy, -1, 1) end
- units.SCALE_S.drag = function(owner, x, y, dx, dy) scale(owner, x, y, dx, dy, 0, 1) end
- local scaleEnd = function(owner)
- owner.scaling = false
- owner.maxWidth, owner.maxHeight = 0, 0
- owner:refresh(true) -- so force a rescale to owner.width, owner.height
- end
- units.SCALE_N.release, units.SCALE_S.release = scaleEnd, scaleEnd
- units.SCALE_E.release, units.SCALE_W.release = scaleEnd, scaleEnd
- units.SCALE_NE.release, units.SCALE_NW.release = scaleEnd, scaleEnd
- units.SCALE_SE.release, units.SCALE_SW.release = scaleEnd, scaleEnd
- -- Panel
- units.PANEL = newbox("panel")
- units.PANEL.drag = function(owner, x, y, dx, dy)
- local content = owner.content
- x, y = owner:contentRelativePos(owner.mouseX, owner.mouseY)
- content:mousemoved(x, y, dx, dy)
- end
- units.PANEL.release = function(owner, x, y, button)
- x, y = owner:contentRelativePos(x, y)
- owner.content:mousereleased(x, y, button)
- end
- units.PANEL.update = function(owner, dt)
- local content = owner.content
- local update = content.update
- if update then update(content, dt) end
- end
- ---------------- MODULE ----------------
- M.init = function(self, x, y, width, height)
- self.theme = BOXUI.theme
- self.x, self.y = x, y
- self.width, self.height = width, height
- self.activeArea = nil
- self.selectedArea = nil
-
- self.mouseX, self.mouseY = 0, 0 -- updated by mousemoved
- self.mousepresses = {} -- for non button 1 clicks on content
-
- -- viewport of content
- self.viewX = 0
- self.viewY = 0
- self.viewH = 0
- self.viewW = 0
- self.viewYMax = 0
- self.viewXMax = 0
-
- -- visibility of elements
- self.hasHandle = false
- self.hasSliderVert = true
- self.hasSliderHori = true
- self.hasClose = false
- self.hasExpand = false
- self.hasShade = false
- self.movable = false
- self.scalable = false
-
-
- self.sliderAdvance = 50
- self.sliderAdvanceTime = 0.050
- self.sliderAdvanceInit = 0.250
-
- self.content = nil
-
- self.wrapVert = false -- adjust height to content
- self.wrapHori = false -- adjust width to content
-
- self.slideDown = false -- after refresh
-
- self.title = "unknown"
-
- self.units = utils.deepcopy(M.units)
-
- self.buffered = true
- --self.canvas = love.graphics.newCanvas(width, height)
- self.maxWidth, self.maxHeight = width, height
- self.viewport = newbox("viewport", 0, 0, width, height)
- end
- --local dummyf = function() end
- --M.expand = dummyf
- --M.focus = dummyf
- -- called by parent to update viewport
- M.updateViewport = function(self, vpx, vpy, vpw, vph)
- setbox(self.viewport, vpx, vpy, vpw, vph)
- end
- -- redraw canvas
- M.redraw = function(self)
- local canvas = self.canvas
- if not canvas then return end
- love.graphics.setCanvas(canvas)
- love.graphics.clear()
- self:drawPassive(0, 0)
- love.graphics.setCanvas()
- end
- -- draw either canvas or dynamically
- M.draw = function(self, x, y)
- local theme = self.theme
- local vp = self.viewport
- x, y = self.x - vp.x + (x or 0), self.y - vp.y + (y or 0)
- if self.scaling then
- local w, h = self.width, self.height
- local bt = theme.borderThickness
- love.graphics.setColor(theme.borderBack)
- love.graphics.rectangle('fill', x, y, w, h)
- love.graphics.setColor(theme.borderFore)
- love.graphics.setLineWidth(bt)
- love.graphics.rectangle('line', x + bt / 2, y + bt / 2, w - bt, h - bt)
- love.graphics.print(("%i x %i"):format(w, h), x + bt, y + bt)
- return
- end
-
- if self.canvas then
- love.graphics.setColor(colorWhite)
- love.graphics.draw(self.canvas, x, y)
- else
- self:drawPassive(x, y)
- end
- self:drawActive(x, y)
-
-
- end
- -- create a new canvas if required, return max dimensions
- M.fit = function(self)
- local selfw, selfh = self.width, self.height
-
- local canvas = self.canvas
- local buffered = self.buffered
- if buffered and not canvas then
- self.canvas = love.graphics.newCanvas(selfw, selfh)
- self.maxWidth, self.maxHeight = selfw, selfh
- return selfw, selfh
- end
-
- local width, height = self.maxWidth, self.maxHeight
- if selfw <= width and selfh <= height then return width, height end
- if canvas then canvas:release() end
- if buffered then
- self.canvas = love.graphics.newCanvas(selfw, selfh)
- end
- self.maxWidth, self.maxHeight = selfw, selfh
- return selfw, selfh
- end
- M.includes = includes
- M.refresh = function(self, redraw)
- self.width, self.height = self:fit()
- self.activeArea = nil
- self.selectedArea = nil
-
- local theme = self.theme
- local st = theme.sliderThickness
- local bt = theme.borderThickness
- local hh = self.hasHandle and theme.handleHeight or 0
- local panelw = self.width - 2 * bt
- local panelh = self.height - 2 * bt - hh
- local content = self.content
- if content.refresh then content:refresh() end
- local cwidth, cheight = content.width, content.height
-
- local stvert = self.hasSliderVert and st or 0
- local sthori = self.hasSliderHori and st or 0
-
- local vert, hori -- overflow check
- if cheight > panelh then
- vert = true
- panelw = panelw - stvert
- end
- if cwidth > panelw then
- hori = true
- panelh = panelh - sthori
- if not vert and cheight > panelh then
- vert = true
- panelw = panelw - stvert
- end
- end
-
- if vert then
- self.viewYMax = cheight - panelh
- else
- self.viewYMax = 0
- stvert = 0
- end
-
- if hori then
- self.viewXMax = cwidth - panelw
- else
- self.viewXMax = 0
- sthori = 0
- end
-
- if self.wrapVert and not vert then
- panelh = cheight
- self.height = panelh + 2 * bt + sthori + hh
- end
-
- if self.wrapHori and not hori then
- panelw = cwidth
- self.width = panelw + 2 * bt + stvert
- end
-
- if content.expand and (panelw > cwidth or panelh > cheight) then
- content:expand(panelw, panelh)
- end
- --content.x, content.y = bt, bt + hh
- content.parent = self
- if content.redraw then content:redraw() end
-
- cwidth, cheight = content.width, content.height
- -- compute boxes fixme: move to theme.lua?
- local u = self.units
- local boxes = {}
- local collidables = {}
- self.boxes = boxes
- self.collidables = collidables
- local box
-
- if self.scalable then
- box = setbox(u.SCALE_SE, panelw + stvert, hh + panelh + sthori, 2 * bt, 2 * bt)
- boxes[box.name] = box; table.insert(collidables, box)
- box = setbox(u.SCALE_NW, 0, 0, 2 * bt, 2 * bt)
- boxes[box.name] = box; table.insert(collidables, box)
- end
-
- if self.hasHandle then
- local i = 1
- local handlew = panelw + stvert
-
- local hbw, hbh = theme.handleButtonWidth, theme.handleButtonHeight
- local hbx = bt + handlew
- local hby = bt + int((hh - hbh) / 2)
- local hbadvance = theme.handlePadVert + hbw
- if self.hasClose then
- hbx = hbx - hbadvance
- box = setbox(u.CLOSE, hbx, hby, hbw, hbh)
- boxes[box.name] = box; table.insert(collidables, box)
- end
- if self.hasShade then
- hbx = hbx - hbadvance
- box =setbox(u.SHADE, hbx, hby, hbw, hbh)
- boxes[box.name] = box; table.insert(collidables, box)
- end
- if self.hasExpand then
- hbx = hbx - hbadvance
- box = setbox(u.EXPAND, hbx, hby, hbw, hbh)
- boxes[box.name] = box; table.insert(collidables, box)
- end
- box = setbox(u.HANDLE, bt, bt, handlew, hh)
- boxes[box.name] = box
- if self.movable then table.insert(collidables, box) end
- end
-
- box = setbox(u.PANEL, bt, bt + hh, panelw, panelh)
- boxes[box.name] = box; table.insert(collidables, box)
-
- if vert and self.hasSliderVert then
- box = setbox(u.SLIDER_V, bt + panelw, bt + hh, st, panelh)
- box.length = max(theme.sliderLengthMin, int(panelh * (panelh / cheight)))
- box.pos = self.slideDown and (panelh - box.length) or 0
- box.dir = 0
- boxes[box.name] = box; table.insert(collidables, box)
- end
-
- if hori and self.hasSliderHori then
- box = setbox(u.SLIDER_H, bt, bt + hh + panelh, panelw, st)
- box.length = max(theme.sliderLengthMin, int(panelw * (panelw / cwidth)))
- box.pos, box.dir = 0, 0
- boxes[box.name] = box; table.insert(collidables, box)
- end
-
- self.viewX, self.viewY = 0, (self.slideDown and self.viewYMax or 0)
- self.viewW, self.viewH = (hori and panelw or cwidth), (vert and panelh or cheight)
-
- content:updateViewport(self.viewX, self.viewY, self.viewW, self.viewH)
-
- self.drawActive = self.theme.draw.containerActive
- self.drawPassive = self.theme.draw.containerPassive
-
- if redraw then self:redraw() end
- end
- M.selectActiveArea = function(self, x, y)
- local prevActive = self.activeArea
- local active = nil
-
- x, y = x - self.x, y - self.y
- local boxes = self.collidables
- for i, v in ipairs(boxes) do
- if not v.hidden and includes(v, x, y) then
- active = v
- break
- end
- end
-
- boxes = self.boxes
- local box = active
- if box then
- if box == boxes.sliderVert then
- local pos, boxpos = y - box.y, box.pos
- if pos < boxpos then box.dir = -1
- elseif pos >= boxpos + box.length then box.dir = 1
- else box.dir = 0 end
- elseif box == boxes.sliderHori then
- local pos, boxpos = x - box.x, box.pos
- if pos < boxpos then box.dir = -1
- elseif pos >= boxpos + box.length then box.dir = 1
- else box.dir = 0 end
- end
- end
- self.activeArea = active
- if prevActive ~= active then
- local content = self.content
- if prevActive == boxes.panel and content.unfocus then content:unfocus()
- elseif active == boxes.panel and content.focus then content:focus() end
- end
- end
- M.contentRelativePos = function(self, x, y)
- local panel = self.boxes.panel
- return x - self.x - panel.x + self.viewX, y - self.y - panel.y + self.viewY
- end
- M.unfocus = function(self)
- local active = self.activeArea
- if not active then return end
- local content = self.content
- if active == self.boxes.panel and content.unfocus then content:unfocus() end
- self.activeArea = nil
- end
- M.wheelmoved = function(self, wx, wy)
- local x, y = self.mouseX, self.mouseY
- --if not self:includes(x, y) then return end
-
- local content = self.content
- local cwm = content.wheelmoved
- if self.activeArea == self.boxes.panel and cwm and cwm(content, wx, wy) then
- x, y = self:contentRelativePos(x, y)
- content:mousemoved(x, y, 0, 0)
- return
- end
-
- local viewymax = self.viewYMax
- if viewymax <= 0 then
- return
- end -- nothing to scroll
-
-
- local viewy = int(self.viewY - wy * self.sliderAdvance)
- viewy = clamp(viewy, 0, viewymax)
- if viewy == self.viewY then
- return
- end
-
- self.viewY = viewy
- local s = self.boxes.sliderVert
- if s then
- s.pos = int((s.height - s.length) * (viewy / viewymax))
- end
- content:updateViewport(self.viewX, self.viewY, self.viewW, self.viewH)
- return true
- end
- M.mousemoved = function(self, x, y, dx, dy)
- self.mouseX, self.mouseY = x, y
- local selected = self.selectedArea
- local drag = selected and selected.drag
- local content = self.content
-
- if drag then
- self.dragging = true
- --if x > 0 and y > 0 then -- fixme: needed for scaling
- drag(self, x, y, dx, dy)
- --end
- return
- end
-
- if not self:includes(x, y) then return self:unfocus() end
- self:selectActiveArea(x, y)
-
-
- if self.activeArea == self.boxes.panel then
- x, y = self:contentRelativePos(x, y)
- content:mousemoved(x, y, dx, dy)
- end
- end
- M.mousepressed = function(self, x, y, button)
- self.dt = 0
- self.advancing = false
-
- if not self:includes(x, y) then return end
-
- if button == 1 then
- self.selectedArea = self.activeArea
- end
-
- if self.activeArea == self.boxes.panel then
- --print(self.id, "pressed", button, self.content.id)
- x, y = self:contentRelativePos(x, y)
- self.content:mousepressed(x, y, button)
- self.mousepresses[button] = true
- end
- end
- local shade_list = {
- panel = true, sliderVert = true, sliderHori = true,
- scaleN = true, scaleNW = true, scaleW = true, scaleSW = true,
- scaleS = true, scaleSE = true, scaleE = true, scaleNE = true,
- --close = false, expand = false, shade = false, handle = false,
- }
- M.rollup = function(self, shade)
- if shade == nil then shade = not self.shaded end
- local boxes = self.boxes
- local handle = boxes.handle
- if shade then
- self.shadedHeight = self.height
- self.height = handle.height + 2 * handle.x
- else
- self.height = self.shadedHeight
- end
- local s
- for k, v in pairs(shade_list) do
- s = boxes[k]
- if v and s then s.hidden = shade end
- end
- self.shaded = shade
-
- self:redraw()
- end
- local premaxvars = {x = true, y = true, width = true, height = true,
- maxWidth = true, maxHeight = true,
- canvas = true,
- wrapVert = true, wrapHori = true,
- scalable = true, movable = true}
-
- M.maximize = function(self, maximize)
- if self.shaded then self:rollup(false) end
- if maximize == nil then maximize = not self.maximized end
- local old
- if maximize then
- old = {}
- self.preMaximize = old
- for k, v in pairs(premaxvars) do
- old[k] = self[k]
- end
-
- local minx, miny, maxw, maxh
- local parent = self.parent
- if parent then
- local box = (parent.boxes and parent.boxes.panel) or parent
- minx, miny = box.x, box.y
- maxw, maxh = box.width, box.height
- else
- minx, miny = 0, 0
- maxw, maxh = love.graphics.getDimensions()
- end
-
- self.x, self.y = minx, miny
- self.width, self.height = maxw, maxh
- self.maxWidth, self.maxHeight = 0, 0 -- force rescale during refresh -> fit
- self.scalable, self.movable = false, false
- self.wrapVert, self.wrapHori = false, false
- else
- old = self.preMaximize
- for k, v in pairs(premaxvars) do
- self[k] = old[k]
- end
- self.width, self.height = self.maxWidth, self.maxHeight
- self.maxWidth, self.maxHeight = 0, 0 -- force rescale during refresh -> fit
- end
- self.maximized = maximize
-
- self:refresh(true)
- end
- M.mousereleased = function(self, x, y, button)
- if button ~=1 then
- if self.mousepresses[button] then
- --print(self.id, "release", button, self.content.id)
- x, y = self:contentRelativePos(x, y)
- self.content:mousereleased(x, y, button)
- end
- return
- end
-
- local selected = self.selectedArea
- if selected == nil then return end
- self.selectedArea = nil
- if self.dragging then
- self.dragging = false
- local release = selected.release -- (drag) release
- if release then release(self, x, y, button) end
-
- if not self:includes(x, y) then return self:unfocus() end
- self:selectActiveArea(x, y)
-
- if self.activeArea == self.boxes.panel then
- x, y = self:contentRelativePos(x, y)
- self.content:mousemoved(x, y, 0, 0)
- end
- return
- end
-
- local click = selected.click
- if click and self.activeArea == selected then return click(self) end
-
- if selected == self.boxes.panel then
- x, y = self:contentRelativePos(x, y)
- self.content:mousereleased(x, y, button)
- end
- end
- M.slideTo = function(self, xdir, ydir, dt)
- self.dt = self.dt + dt
- if not self.advancing then
- if self.dt < self.sliderAdvanceInit then return end
- self.advancing = true; self.dt = self.dt - self.sliderAdvanceInit
- end
- if self.dt < self.sliderAdvanceTime then return end
- self.dt = self.dt - self.sliderAdvanceTime
- local boxes = self.boxes
- local panel = boxes.panel
- local x, y = self.mouseX, self.mouseY
- x, y = x - self.x - panel.x, y - self.y - panel.y
-
- local s, a, a_len, a_max, targetpos
- dt = self.sliderAdvance -- constant time
- local changed = false
- if xdir ~= 0 then
- a = int(self.viewX + xdir * dt)
- a_len = self.viewW
- a_max = self.viewXMax
-
- targetpos = int(clamp(x + (x * a_max) / a_len - a_len / 2, 0, a_max))
- if xdir * (a - targetpos) > 0 then a = targetpos end
-
- if a ~= self.viewX then
- self.viewX = a
- s = boxes.sliderHori
- if s then
- s.pos = int(((s.width - s.length) * a) / a_max)
- if a == targetpos then s.dir = 0 end
- end
- changed = true
- end
- end
-
- if ydir ~= 0 then
- a = int(self.viewY + ydir * dt) -- fixme use trim
- a_len = self.viewH
- a_max = self.viewYMax
-
- targetpos = int(clamp(y + (y * a_max) / a_len - a_len / 2, 0, a_max))
- if ydir * (a - targetpos) > 0 then a = targetpos end
-
- if a ~= self.viewY then
- self.viewY = a
- s = boxes.sliderVert
- if s then
- s.pos = int(((s.height - s.length) * a) / a_max)
- if a == targetpos then s.dir = 0 end
- end
- changed = true
- end
- end
-
- if changed then
- self.content:updateViewport(self.viewX, self.viewY, self.viewW, self.viewH)
- end
- end
- M.update = function(self, dt)
- local active, selected = self.activeArea, self.selectedArea
- if not selected or selected ~= active or not selected.update then return end
-
- selected.update(self, dt)
- end
- BOXUI.add(M)
- end
|