123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- return function(BOXUI)
- local utils = BOXUI.utils
- local colorWhite = {1, 1, 1}
- local int = utils.int
- local max = utils.max
- local clamp = utils.clamp
- local ListContent = utils.newclass("list_content")
- local lcmt = ListContent
- ListContent.template_theme = {
- itemHeight = 32, itemPadVert = 8, itemPadHori = 8,
- itemBack = {0, 0, 1},
- itemFore = {0, 1, 0}, itemForeActive = {1, 1, 0},
- }
- ListContent.init = function(self, x, y, width, height)
- self.theme = BOXUI.theme
- self.x, self.y = x, y
- self.width, self.height = width, height
-
- self.items = nil
- self.itemActive = nil
- self.itemSelected = nil
- self.onClick = nil
- self.font = love.graphics.getFont()
-
- self.canvas = love.graphics.newCanvas(width, height)
- --self.canvas:setWrap("clampzero", "clampzero")
- self.quad = love.graphics.newQuad(0, 0, width, height, width, height)
- end
- ListContent.insert = function(self, text, context, refresh)
- local entry = {text = text, context = context}
- if not self.items then self.items = {} end
- table.insert(self.items, entry)
- if refresh == true then self:refresh() end
- end
- ListContent.setItems = function(self, t, refresh)
- self.items = t
- if refresh == true then self:refresh() end
- end
- ListContent.selectActiveItem = function(self, x, y)
- x, y = x - self.x, y - self.y
- if not self.items then return end
- local prevActive = self.itemActive
- local active = nil
- local theme = self.theme
- local height = theme.itemHeight
- local advance = height + theme.itemPadVert
- local relY = y % advance
-
- if relY >= 0 and relY < height then
- active = 1 + int(y / advance)
- if active < 1 or active > #self.items then active = nil end
- end
- self.itemActive = active
- if prevActive ~= active then
- return true
- end
- end
- ListContent.unfocus = function(self)
- self.itemActive = nil
- end
- ListContent.focus = function(self)
- end
- ListContent.mousemoved = function(self, x, y, dx, dy)
- self:selectActiveItem(x, y)
- end
- ListContent.mousepressed = function(self, x, y, button)
- if button ~= 1 then return end
- self.itemSelected = self.itemActive
- end
- ListContent.mousereleased = function(self, x, y, button)
- local selected, active = self.itemSelected, self.itemActive
- if button ~= 1 then return end
- if selected == nil then self:selectActiveItem(x, y) return end
-
- self.itemSelected = nil
- --self.itemActive = nil
- local item = self.items[selected]
-
- if selected == active then
- if item and self.onClick then
- self.onClick(item)
- end
- end
- end
- local lineWidth = function(font, text, icon, pad)
- local texttype = type(text)
- local w = icon and (icon:getWidth() + pad) or 0
- if texttype == "string" then
- w = w + font:getWidth(text)
- elseif texttype == "table" then
- for i = 2, #text, 2 do w = w + font:getWidth(text[i]) end
- end
-
- return w
- end
- ListContent.getLineWidth = function(self)
- local theme = self.theme
- local font = self.font
- local itemph = theme.itemPadHori
- local width = 0
- for i, v in ipairs(self.items) do
- width = max(width, lineWidth(font, v.text, v.icon, itemph))
- end
- return width + 2 * itemph
- end
- -- create a new canvas if required, return canvas size
- ListContent.fitCanvas = function(self)
- local selfw, selfh = self.width, self.height
- local canvas = self.canvas
- if not canvas then return selfw, selfh end
-
- local width, height = canvas:getDimensions()
- if selfw <= width and selfh <= height then return width, height end
- canvas:release()
- self.canvas = love.graphics.newCanvas(selfw, selfh)
- return selfw, selfh
- end
- ListContent.refresh = function(self, redraw)
- self.itemActive = nil
- self.itemSelected = nil
- local numitems = self.items and #self.items or 0
- local theme = self.theme
-
-
- if numitems == 0 then
- --self.canvas:renderTo(love.graphics.clear)
- self.width, self.height = theme.itemPadHori, theme.itemPadVert
- --self.overlay:renderTo(love.graphics.clear)
- return
- end
-
- local itemh = theme.itemHeight
- local itempv = theme.itemPadVert
- local itemph = theme.itemPadHori
-
- self.height = itemh * numitems + itempv * (numitems - 1)
-
- self.width = self:getLineWidth()
-
- self:fitCanvas()
-
- self.drawPassive = theme.draw.listContentPassive
- if redraw then self:redraw() end
- end
- ListContent.expand = function(self, width, height)
- if self.width < width then self.width = width end
- self:fitCanvas()
- end
- ListContent.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
- ListContent.updateViewport = function(self, vpx, vpy, vpw, vph)
- local canvas = self.canvas
- local width, height
- if self.canvas then width, height = canvas:getDimensions()
- else width, height = self.width, self.height end
- self.quad:setViewport(vpx, vpy, vpw, vph, width, height)
- end
- ListContent.draw = function(self, x, y)
- x, y = self.x + (x or 0), self.y + (y or 0)
- if self.canvas then
- love.graphics.setColor(colorWhite)
- love.graphics.draw(self.canvas, self.quad, x, y)
- else
- local vpx, vpy, vpw, vph = self.quad:getViewport()
- self:drawPassive(x - vpx, y - vpy, vpy, vpy + vph) -- not a typo; y = l1, l2
- end
- end
- BOXUI.add(ListContent)
- local Container = BOXUI.container
- local M = utils.newclass("list", Container)
- --utils.freshenprops(M.template_theme, default_theme)
- --local create = M.create
- M.init = function(self, x, y, width, height)
- Container.init(self, x, y, width, height)
- self.wrapHori = false
- self.wrapVert = false
- local list = ListContent.new(0,0, 10, 10)
-
- self.content = list
- self.list = list -- alias
- end
- M.insert = function(self, text, context, refresh)
- self.content:insert(text, context)
- if refresh == true then self:refresh(true) end
- end
- M.setItems = function(self, t, refresh)
- self.content:setItems(t)
- if refresh == true then self:refresh(true) end
- end
- M.refresh = function(self, redraw)
- Container.refresh(self, redraw)
- self.drawOverlay = self.theme.draw.listOverlay
- end
- BOXUI.add(M)
- end
|