356 lines
11 KiB
Lua
356 lines
11 KiB
Lua
local utils = require("utils")
|
|
local tHex = require("tHex")
|
|
|
|
return function(name, basalt)
|
|
local base = basalt.getObject("ChangeableObject")(name, basalt)
|
|
local objectType = "Treeview"
|
|
|
|
local nodes = {}
|
|
local itemSelectedBG = colors.black
|
|
local itemSelectedFG = colors.lightGray
|
|
local selectionColorActive = true
|
|
local textAlign = "left"
|
|
local xOffset, yOffset = 0, 0
|
|
local scrollable = true
|
|
|
|
base:setSize(16, 8)
|
|
base:setZIndex(5)
|
|
|
|
local function newNode(text, expandable)
|
|
text = text or ""
|
|
expandable = expandable or false
|
|
local expanded = false
|
|
local parent = nil
|
|
local children = {}
|
|
|
|
local node = {}
|
|
|
|
local onSelect
|
|
|
|
node = {
|
|
getChildren = function(self)
|
|
return children
|
|
end,
|
|
|
|
setParent = function(self, p)
|
|
if(parent~=nil)then
|
|
parent.removeChild(parent.findChildrenByText(node.getText()))
|
|
end
|
|
parent = p
|
|
base:updateDraw()
|
|
return node
|
|
end,
|
|
|
|
getParent = function(self)
|
|
return parent
|
|
end,
|
|
|
|
addChild = function(self, text, expandable)
|
|
local childNode = newNode(text, expandable)
|
|
childNode.setParent(node)
|
|
table.insert(children, childNode)
|
|
base:updateDraw()
|
|
return childNode
|
|
end,
|
|
|
|
setExpanded = function(self, exp)
|
|
if(expandable)then
|
|
expanded = exp
|
|
end
|
|
base:updateDraw()
|
|
return node
|
|
end,
|
|
|
|
isExpanded = function(self)
|
|
return expanded
|
|
end,
|
|
|
|
onSelect = function(self, ...)
|
|
for _,v in pairs(table.pack(...))do
|
|
if(type(v)=="function")then
|
|
onSelect = v
|
|
end
|
|
end
|
|
return node
|
|
end,
|
|
|
|
callOnSelect = function(self)
|
|
if(onSelect~=nil)then
|
|
onSelect(node)
|
|
end
|
|
end,
|
|
|
|
setExpandable = function(self, expandable)
|
|
expandable = expandable
|
|
base:updateDraw()
|
|
return node
|
|
end,
|
|
|
|
isExpandable = function(self)
|
|
return expandable
|
|
end,
|
|
|
|
removeChild = function(self, index)
|
|
if(type(index)=="table")then
|
|
for k,v in pairs(index)do
|
|
if(v==index)then
|
|
index = k
|
|
break
|
|
end
|
|
end
|
|
end
|
|
table.remove(children, index)
|
|
base:updateDraw()
|
|
return node
|
|
end,
|
|
|
|
findChildrenByText = function(self, searchText)
|
|
local foundNodes = {}
|
|
for _, child in ipairs(children) do
|
|
if string.find(child.getText(), searchText) then
|
|
table.insert(foundNodes, child)
|
|
end
|
|
end
|
|
return foundNodes
|
|
end,
|
|
|
|
getText = function(self)
|
|
return text
|
|
end,
|
|
|
|
setText = function(self, t)
|
|
text = t
|
|
base:updateDraw()
|
|
return node
|
|
end
|
|
}
|
|
|
|
return node
|
|
end
|
|
|
|
local root = newNode("Root", true)
|
|
root:setExpanded(true)
|
|
|
|
local object = {
|
|
init = function(self)
|
|
local parent = self:getParent()
|
|
self:listenEvent("mouse_click")
|
|
self:listenEvent("mouse_scroll")
|
|
return base.init(self)
|
|
end,
|
|
|
|
getBase = function(self)
|
|
return base
|
|
end,
|
|
|
|
getType = function(self)
|
|
return objectType
|
|
end,
|
|
|
|
isType = function(self, t)
|
|
return objectType == t or base.isType ~= nil and base.isType(t) or false
|
|
end,
|
|
|
|
setOffset = function(self, x, y)
|
|
xOffset = x
|
|
yOffset = y
|
|
return self
|
|
end,
|
|
|
|
setXOffset = function(self, x)
|
|
return self:setOffset(x, yOffset)
|
|
end,
|
|
|
|
setYOffset = function(self, y)
|
|
return self:setOffset(xOffset, y)
|
|
end,
|
|
|
|
getOffset = function(self)
|
|
return xOffset, yOffset
|
|
end,
|
|
|
|
getXOffset = function(self)
|
|
return xOffset
|
|
end,
|
|
|
|
getYOffset = function(self)
|
|
return yOffset
|
|
end,
|
|
|
|
setScrollable = function(self, scroll)
|
|
scrollable = scroll
|
|
return self
|
|
end,
|
|
|
|
getScrollable = function(self, scroll)
|
|
return scrollable
|
|
end,
|
|
|
|
setSelectionColor = function(self, bgCol, fgCol, active)
|
|
itemSelectedBG = bgCol or self:getBackground()
|
|
itemSelectedFG = fgCol or self:getForeground()
|
|
selectionColorActive = active~=nil and active or true
|
|
self:updateDraw()
|
|
return self
|
|
end,
|
|
|
|
setSelectionBG = function(self, bgCol)
|
|
return self:setSelectionColor(bgCol, nil, selectionColorActive)
|
|
end,
|
|
|
|
setSelectionFG = function(self, fgCol)
|
|
return self:setSelectionColor(nil, fgCol, selectionColorActive)
|
|
end,
|
|
|
|
getSelectionColor = function(self)
|
|
return itemSelectedBG, itemSelectedFG
|
|
end,
|
|
|
|
getSelectionBG = function(self)
|
|
return itemSelectedBG
|
|
end,
|
|
|
|
getSelectionFG = function(self)
|
|
return itemSelectedFG
|
|
end,
|
|
|
|
isSelectionColorActive = function(self)
|
|
return selectionColorActive
|
|
end,
|
|
|
|
getRoot = function(self)
|
|
return root
|
|
end,
|
|
|
|
setRoot = function(self, node)
|
|
root = node
|
|
node.setParent(nil)
|
|
return self
|
|
end,
|
|
|
|
onSelect = function(self, ...)
|
|
for _,v in pairs(table.pack(...))do
|
|
if(type(v)=="function")then
|
|
self:registerEvent("treeview_select", v)
|
|
end
|
|
end
|
|
return self
|
|
end,
|
|
|
|
selectionHandler = function(self, node)
|
|
node.callOnSelect(node)
|
|
self:sendEvent("treeview_select", node)
|
|
return self
|
|
end,
|
|
|
|
mouseHandler = function(self, button, x, y)
|
|
if base.mouseHandler(self, button, x, y) then
|
|
local currentLine = 1 - yOffset
|
|
local obx, oby = self:getAbsolutePosition()
|
|
local w, h = self:getSize()
|
|
local function checkNodeClick(node, level)
|
|
if y == oby+currentLine-1 then
|
|
if x >= obx and x < obx + w then
|
|
node:setExpanded(not node:isExpanded())
|
|
self:selectionHandler(node)
|
|
self:setValue(node)
|
|
self:updateDraw()
|
|
return true
|
|
end
|
|
end
|
|
currentLine = currentLine + 1
|
|
if node:isExpanded() then
|
|
for _, child in ipairs(node:getChildren()) do
|
|
if checkNodeClick(child, level + 1) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
for _, item in ipairs(root:getChildren()) do
|
|
if checkNodeClick(item, 1) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end,
|
|
|
|
scrollHandler = function(self, dir, x, y)
|
|
if base.scrollHandler(self, dir, x, y) then
|
|
if scrollable then
|
|
local _, h = self:getSize()
|
|
yOffset = yOffset + dir
|
|
|
|
if yOffset < 0 then
|
|
yOffset = 0
|
|
end
|
|
|
|
if dir >= 1 then
|
|
local visibleLines = 0
|
|
local function countVisibleLines(node, level)
|
|
visibleLines = visibleLines + 1
|
|
if node:isExpanded() then
|
|
for _, child in ipairs(node:getChildren()) do
|
|
countVisibleLines(child, level + 1)
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, item in ipairs(root:getChildren()) do
|
|
countVisibleLines(item, 1)
|
|
end
|
|
|
|
if visibleLines > h then
|
|
if yOffset > visibleLines - h then
|
|
yOffset = visibleLines - h
|
|
end
|
|
else
|
|
yOffset = yOffset - 1
|
|
end
|
|
end
|
|
self:updateDraw()
|
|
end
|
|
return true
|
|
end
|
|
return false
|
|
end,
|
|
|
|
draw = function(self)
|
|
base.draw(self)
|
|
self:addDraw("treeview", function()
|
|
local currentLine = 1 - yOffset
|
|
local lastClickedNode = self:getValue()
|
|
local function drawNode(node, level)
|
|
local w, h = self:getSize()
|
|
|
|
if currentLine >= 1 and currentLine <= h then
|
|
local bg = (node == lastClickedNode) and itemSelectedBG or self:getBackground()
|
|
local fg = (node == lastClickedNode) and itemSelectedFG or self:getForeground()
|
|
|
|
local text = node.getText()
|
|
self:addBlit(1 + level + xOffset, currentLine, text, tHex[fg]:rep(#text), tHex[bg]:rep(#text))
|
|
end
|
|
|
|
currentLine = currentLine + 1
|
|
|
|
if node:isExpanded() then
|
|
for _, child in ipairs(node:getChildren()) do
|
|
drawNode(child, level + 1)
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, item in ipairs(root:getChildren()) do
|
|
drawNode(item, 1)
|
|
end
|
|
end)
|
|
end,
|
|
|
|
|
|
}
|
|
|
|
object.__index = object
|
|
return setmetatable(object, base)
|
|
end |