IsInBounds Fix
This commit is contained in:
@@ -259,15 +259,12 @@ end
|
|||||||
--- Destroys the element and cleans up all references
|
--- Destroys the element and cleans up all references
|
||||||
--- @shortDescription Destroys the element and cleans up all references
|
--- @shortDescription Destroys the element and cleans up all references
|
||||||
function BaseElement:destroy()
|
function BaseElement:destroy()
|
||||||
self._destroyed = true
|
|
||||||
self:removeAllObservers()
|
|
||||||
self:setFocused(false)
|
|
||||||
for event in pairs(self._registeredEvents) do
|
|
||||||
self:listenEvent(event, false)
|
|
||||||
end
|
|
||||||
if(self.parent) then
|
if(self.parent) then
|
||||||
self.parent:removeChild(self)
|
self.parent:removeChild(self)
|
||||||
end
|
end
|
||||||
|
self._destroyed = true
|
||||||
|
self:removeAllObservers()
|
||||||
|
self:setFocused(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Requests a render update for this element
|
--- Requests a render update for this element
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ local function sortAndFilterChildren(self, children)
|
|||||||
local visibleChildren = {}
|
local visibleChildren = {}
|
||||||
|
|
||||||
for _, child in ipairs(children) do
|
for _, child in ipairs(children) do
|
||||||
if self:isChildVisible(child) and child.get("visible") then
|
if self:isChildVisible(child) and child.get("visible") and not child._destroyed then
|
||||||
table.insert(visibleChildren, child)
|
table.insert(visibleChildren, child)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -250,7 +250,7 @@ function Container:registerChildEvent(child, eventName)
|
|||||||
end
|
end
|
||||||
|
|
||||||
for _, registeredChild in ipairs(self._values.childrenEvents[eventName]) do
|
for _, registeredChild in ipairs(self._values.childrenEvents[eventName]) do
|
||||||
if registeredChild == child then
|
if registeredChild.get("id") == child.get("id") then
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -347,13 +347,11 @@ end
|
|||||||
|
|
||||||
local function convertMousePosition(self, event, ...)
|
local function convertMousePosition(self, event, ...)
|
||||||
local args = {...}
|
local args = {...}
|
||||||
if event then
|
if event:find("mouse_") then
|
||||||
if event:find("mouse_") then
|
local button, absX, absY = ...
|
||||||
local button, absX, absY = ...
|
local xOffset, yOffset = self.get("offsetX"), self.get("offsetY")
|
||||||
local xOffset, yOffset = self.get("offsetX"), self.get("offsetY")
|
local relX, relY = self:getRelativePosition(absX + xOffset, absY + yOffset)
|
||||||
local relX, relY = self:getRelativePosition(absX + xOffset, absY + yOffset)
|
args = {button, relX, relY}
|
||||||
args = {button, relX, relY}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return args
|
return args
|
||||||
end
|
end
|
||||||
@@ -488,13 +486,10 @@ end
|
|||||||
--- @return boolean handled Whether the event was handled
|
--- @return boolean handled Whether the event was handled
|
||||||
--- @protected
|
--- @protected
|
||||||
function Container:mouse_scroll(direction, x, y)
|
function Container:mouse_scroll(direction, x, y)
|
||||||
local args = convertMousePosition(self, "mouse_scroll", direction, x, y)
|
|
||||||
local success, child = self:callChildrenEvent(true, "mouse_scroll", table.unpack(args))
|
|
||||||
if(success)then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
if(VisualElement.mouse_scroll(self, direction, x, y))then
|
if(VisualElement.mouse_scroll(self, direction, x, y))then
|
||||||
return true
|
local args = convertMousePosition(self, "mouse_scroll", direction, x, y)
|
||||||
|
local success, child = self:callChildrenEvent(true, "mouse_scroll", table.unpack(args))
|
||||||
|
return success
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -690,10 +685,6 @@ end
|
|||||||
--- @private
|
--- @private
|
||||||
function Container:destroy()
|
function Container:destroy()
|
||||||
if not self:isType("BaseFrame") then
|
if not self:isType("BaseFrame") then
|
||||||
for _, child in ipairs(self.get("children")) do
|
|
||||||
child:destroy()
|
|
||||||
end
|
|
||||||
self.set("childrenSorted", false)
|
|
||||||
VisualElement.destroy(self)
|
VisualElement.destroy(self)
|
||||||
return self
|
return self
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -787,7 +787,6 @@ function Flexbox:addChild(element)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Removes a child element from the flexbox
|
|
||||||
--- @shortDescription Removes a child element from the flexbox
|
--- @shortDescription Removes a child element from the flexbox
|
||||||
--- @param element Element The child element to remove
|
--- @param element Element The child element to remove
|
||||||
--- @return Flexbox self The flexbox instance
|
--- @return Flexbox self The flexbox instance
|
||||||
|
|||||||
@@ -19,6 +19,13 @@ Frame.defineProperty(Frame, "draggable", {default = false, type = "boolean", set
|
|||||||
end})
|
end})
|
||||||
---@property draggingMap table {} The map of dragging positions
|
---@property draggingMap table {} The map of dragging positions
|
||||||
Frame.defineProperty(Frame, "draggingMap", {default = {{x=1, y=1, width="width", height=1}}, type = "table"})
|
Frame.defineProperty(Frame, "draggingMap", {default = {{x=1, y=1, width="width", height=1}}, type = "table"})
|
||||||
|
---@property scrollable boolean false Whether the frame is scrollable
|
||||||
|
Frame.defineProperty(Frame, "scrollable", {default = false, type = "boolean", setter=function(self, value)
|
||||||
|
if value then
|
||||||
|
self:listenEvent("mouse_scroll", true)
|
||||||
|
end
|
||||||
|
return value
|
||||||
|
end})
|
||||||
|
|
||||||
--- Creates a new Frame instance
|
--- Creates a new Frame instance
|
||||||
--- @shortDescription Creates a new Frame instance
|
--- @shortDescription Creates a new Frame instance
|
||||||
@@ -94,9 +101,12 @@ end
|
|||||||
--- @return boolean handled Whether the event was handled
|
--- @return boolean handled Whether the event was handled
|
||||||
--- @protected
|
--- @protected
|
||||||
function Frame:mouse_up(button, x, y)
|
function Frame:mouse_up(button, x, y)
|
||||||
self.dragging = false
|
if self.dragging then
|
||||||
self.dragStartX = nil
|
self.dragging = false
|
||||||
self.dragStartY = nil
|
self.dragStartX = nil
|
||||||
|
self.dragStartY = nil
|
||||||
|
return true
|
||||||
|
end
|
||||||
return Container.mouse_up(self, button, x, y)
|
return Container.mouse_up(self, button, x, y)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -121,4 +131,58 @@ function Frame:mouse_drag(button, x, y)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- @shortDescription Calculates the total height of all children elements
|
||||||
|
--- @return number height The total height needed for all children
|
||||||
|
--- @protected
|
||||||
|
function Frame:getChildrenHeight()
|
||||||
|
local maxHeight = 0
|
||||||
|
local children = self.get("children")
|
||||||
|
|
||||||
|
for _, child in ipairs(children) do
|
||||||
|
if child.get("visible") then
|
||||||
|
local childY = child.get("y")
|
||||||
|
local childHeight = child.get("height")
|
||||||
|
local totalHeight = childY + childHeight - 1
|
||||||
|
|
||||||
|
if totalHeight > maxHeight then
|
||||||
|
maxHeight = totalHeight
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return maxHeight
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @shortDescription Handles mouse scroll events
|
||||||
|
--- @param direction number The scroll direction
|
||||||
|
--- @param x number The x position of the scroll
|
||||||
|
--- @param y number The y position of the scroll
|
||||||
|
--- @return boolean handled Whether the event was handled
|
||||||
|
--- @protected
|
||||||
|
function Frame:mouse_scroll(direction, x, y)
|
||||||
|
if Container.mouse_scroll(self, direction, x, y) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.get("scrollable") then
|
||||||
|
local relX, relY = self:getRelativePosition(x, y)
|
||||||
|
local width = self.get("width")
|
||||||
|
local height = self.get("height")
|
||||||
|
|
||||||
|
if relX >= 1 and relX <= width and relY >= 1 and relY <= height then
|
||||||
|
local childrenHeight = self:getChildrenHeight()
|
||||||
|
local currentOffset = self.get("offsetY")
|
||||||
|
local maxScroll = math.max(0, childrenHeight - height)
|
||||||
|
|
||||||
|
local newOffset = currentOffset + direction
|
||||||
|
newOffset = math.max(0, math.min(maxScroll, newOffset))
|
||||||
|
|
||||||
|
self.set("offsetY", newOffset)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
return Frame
|
return Frame
|
||||||
@@ -173,38 +173,6 @@ function List:mouse_scroll(direction, x, y)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Selects an item by index
|
|
||||||
--- @shortDescription Selects an item by index
|
|
||||||
--- @param index number The index of the item to select
|
|
||||||
--- @return List self The List instance
|
|
||||||
function List:selectItem(index)
|
|
||||||
local items = self.get("items")
|
|
||||||
|
|
||||||
if not self.get("multiSelection") then
|
|
||||||
for _, item in ipairs(items) do
|
|
||||||
if type(item) == "table" then
|
|
||||||
item.selected = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local item = items[index]
|
|
||||||
if type(item) == "string" then
|
|
||||||
item = {text = item}
|
|
||||||
items[index] = item
|
|
||||||
end
|
|
||||||
|
|
||||||
item.selected = true
|
|
||||||
|
|
||||||
if item.callback then
|
|
||||||
item.callback(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
self:fireEvent("select", index, item)
|
|
||||||
self:updateRender()
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Registers a callback for the select event
|
--- Registers a callback for the select event
|
||||||
--- @shortDescription Registers a callback for the select event
|
--- @shortDescription Registers a callback for the select event
|
||||||
--- @param callback function The callback function to register
|
--- @param callback function The callback function to register
|
||||||
|
|||||||
@@ -23,7 +23,13 @@ Table.defineProperty(Table, "columns", {default = {}, type = "table", canTrigger
|
|||||||
return t
|
return t
|
||||||
end})
|
end})
|
||||||
---@property data table {} The table data as array of row arrays
|
---@property data table {} The table data as array of row arrays
|
||||||
Table.defineProperty(Table, "data", {default = {}, type = "table", canTriggerRender = true})
|
Table.defineProperty(Table, "data", {default = {}, type = "table", canTriggerRender = true, setter=function(self, value)
|
||||||
|
self.set("scrollOffset", 0)
|
||||||
|
self.set("selectedRow", nil)
|
||||||
|
self.set("sortColumn", nil)
|
||||||
|
self.set("sortDirection", "asc")
|
||||||
|
return value
|
||||||
|
end})
|
||||||
---@property selectedRow number? nil Currently selected row index
|
---@property selectedRow number? nil Currently selected row index
|
||||||
Table.defineProperty(Table, "selectedRow", {default = nil, type = "number", canTriggerRender = true})
|
Table.defineProperty(Table, "selectedRow", {default = nil, type = "number", canTriggerRender = true})
|
||||||
---@property headerColor color blue Color of the column headers
|
---@property headerColor color blue Color of the column headers
|
||||||
@@ -33,9 +39,9 @@ Table.defineProperty(Table, "selectedColor", {default = colors.lightBlue, type =
|
|||||||
---@property gridColor color gray Color of grid lines
|
---@property gridColor color gray Color of grid lines
|
||||||
Table.defineProperty(Table, "gridColor", {default = colors.gray, type = "color"})
|
Table.defineProperty(Table, "gridColor", {default = colors.gray, type = "color"})
|
||||||
---@property sortColumn number? nil Currently sorted column index
|
---@property sortColumn number? nil Currently sorted column index
|
||||||
Table.defineProperty(Table, "sortColumn", {default = nil, type = "number"})
|
Table.defineProperty(Table, "sortColumn", {default = nil, type = "number", canTriggerRender = true})
|
||||||
---@property sortDirection string "asc" Sort direction ("asc" or "desc")
|
---@property sortDirection string "asc" Sort direction ("asc" or "desc")
|
||||||
Table.defineProperty(Table, "sortDirection", {default = "asc", type = "string"})
|
Table.defineProperty(Table, "sortDirection", {default = "asc", type = "string", canTriggerRender = true})
|
||||||
---@property scrollOffset number 0 Current scroll position
|
---@property scrollOffset number 0 Current scroll position
|
||||||
Table.defineProperty(Table, "scrollOffset", {default = 0, type = "number", canTriggerRender = true})
|
Table.defineProperty(Table, "scrollOffset", {default = 0, type = "number", canTriggerRender = true})
|
||||||
|
|
||||||
@@ -144,17 +150,11 @@ function Table:mouse_click(button, x, y)
|
|||||||
if relY > 1 then
|
if relY > 1 then
|
||||||
local rowIndex = relY - 2 + self.get("scrollOffset")
|
local rowIndex = relY - 2 + self.get("scrollOffset")
|
||||||
if rowIndex >= 0 and rowIndex < #self.get("data") then
|
if rowIndex >= 0 and rowIndex < #self.get("data") then
|
||||||
local newIndex = rowIndex + 1
|
self.set("selectedRow", rowIndex + 1)
|
||||||
self.set("selectedRow", newIndex)
|
|
||||||
self:fireEvent("select", newIndex, self.get("data")[newIndex])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function Table:onSelect(callback)
|
return true
|
||||||
self:registerCallback("select", callback)
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @shortDescription Handles scrolling through the table data
|
--- @shortDescription Handles scrolling through the table data
|
||||||
@@ -168,7 +168,7 @@ function Table:mouse_scroll(direction, x, y)
|
|||||||
local data = self.get("data")
|
local data = self.get("data")
|
||||||
local height = self.get("height")
|
local height = self.get("height")
|
||||||
local visibleRows = height - 2
|
local visibleRows = height - 2
|
||||||
local maxScroll = math.max(0, #data - visibleRows + 1)
|
local maxScroll = math.max(0, #data - visibleRows - 1)
|
||||||
local newOffset = math.min(maxScroll, math.max(0, self.get("scrollOffset") + direction))
|
local newOffset = math.min(maxScroll, math.max(0, self.get("scrollOffset") + direction))
|
||||||
|
|
||||||
self.set("scrollOffset", newOffset)
|
self.set("scrollOffset", newOffset)
|
||||||
@@ -189,14 +189,31 @@ function Table:render()
|
|||||||
local height = self.get("height")
|
local height = self.get("height")
|
||||||
local width = self.get("width")
|
local width = self.get("width")
|
||||||
|
|
||||||
|
local totalWidth = 0
|
||||||
|
local lastVisibleColumn = #columns
|
||||||
|
for i, col in ipairs(columns) do
|
||||||
|
if totalWidth + col.width > width then
|
||||||
|
if i == 1 then
|
||||||
|
col.visibleWidth = width
|
||||||
|
else
|
||||||
|
col.visibleWidth = width - totalWidth
|
||||||
|
lastVisibleColumn = i
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
col.visibleWidth = col.width
|
||||||
|
totalWidth = totalWidth + col.width
|
||||||
|
end
|
||||||
|
|
||||||
local currentX = 1
|
local currentX = 1
|
||||||
for i, col in ipairs(columns) do
|
for i, col in ipairs(columns) do
|
||||||
|
if i > lastVisibleColumn then break end
|
||||||
local text = col.name
|
local text = col.name
|
||||||
if i == sortCol then
|
if i == sortCol then
|
||||||
text = text .. (self.get("sortDirection") == "asc" and "\30" or "\31")
|
text = text .. (self.get("sortDirection") == "asc" and "\30" or "\31")
|
||||||
end
|
end
|
||||||
self:textFg(currentX, 1, text:sub(1, col.width), self.get("headerColor"))
|
self:textFg(currentX, 1, text:sub(1, col.visibleWidth), self.get("headerColor"))
|
||||||
currentX = currentX + col.width
|
currentX = currentX + col.visibleWidth
|
||||||
end
|
end
|
||||||
|
|
||||||
for y = 2, height do
|
for y = 2, height do
|
||||||
@@ -208,17 +225,18 @@ function Table:render()
|
|||||||
local bg = (rowIndex + 1) == selected and self.get("selectedColor") or self.get("background")
|
local bg = (rowIndex + 1) == selected and self.get("selectedColor") or self.get("background")
|
||||||
|
|
||||||
for i, col in ipairs(columns) do
|
for i, col in ipairs(columns) do
|
||||||
|
if i > lastVisibleColumn then break end
|
||||||
local cellText = tostring(rowData[i] or "")
|
local cellText = tostring(rowData[i] or "")
|
||||||
local paddedText = cellText .. string.rep(" ", col.width - #cellText)
|
local paddedText = cellText .. string.rep(" ", col.visibleWidth - #cellText)
|
||||||
if i < #columns then
|
if i < lastVisibleColumn then
|
||||||
paddedText = string.sub(paddedText, 1, col.width - 1) .. " "
|
paddedText = string.sub(paddedText, 1, col.visibleWidth - 1) .. " "
|
||||||
end
|
end
|
||||||
local finalText = string.sub(paddedText, 1, col.width)
|
local finalText = string.sub(paddedText, 1, col.visibleWidth)
|
||||||
local finalForeground = string.rep(tHex[self.get("foreground")], #finalText)
|
local finalForeground = string.rep(tHex[self.get("foreground")], col.visibleWidth)
|
||||||
local finalBackground = string.rep(tHex[bg], #finalText)
|
local finalBackground = string.rep(tHex[bg], col.visibleWidth)
|
||||||
|
|
||||||
self:blit(currentX, y, finalText, finalForeground, finalBackground)
|
self:blit(currentX, y, finalText, finalForeground, finalBackground)
|
||||||
currentX = currentX + col.width
|
currentX = currentX + col.visibleWidth
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:blit(1, y, string.rep(" ", self.get("width")),
|
self:blit(1, y, string.rep(" ", self.get("width")),
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ VisualElement.registerEventCallback(VisualElement, "ClickUp", "mouse_up", "mouse
|
|||||||
VisualElement.registerEventCallback(VisualElement, "Drag", "mouse_drag", "mouse_click", "mouse_up")
|
VisualElement.registerEventCallback(VisualElement, "Drag", "mouse_drag", "mouse_click", "mouse_up")
|
||||||
VisualElement.registerEventCallback(VisualElement, "Scroll", "mouse_scroll")
|
VisualElement.registerEventCallback(VisualElement, "Scroll", "mouse_scroll")
|
||||||
VisualElement.registerEventCallback(VisualElement, "Enter", "mouse_enter", "mouse_move")
|
VisualElement.registerEventCallback(VisualElement, "Enter", "mouse_enter", "mouse_move")
|
||||||
VisualElement.registerEventCallback(VisualElement, "Leave", "mouse_leave", "mouse_move")
|
VisualElement.registerEventCallback(VisualElement, "LeEave", "mouse_leave", "mouse_move")
|
||||||
VisualElement.registerEventCallback(VisualElement, "Focus", "focus", "blur")
|
VisualElement.registerEventCallback(VisualElement, "Focus", "focus", "blur")
|
||||||
VisualElement.registerEventCallback(VisualElement, "Blur", "blur", "focus")
|
VisualElement.registerEventCallback(VisualElement, "Blur", "blur", "focus")
|
||||||
VisualElement.registerEventCallback(VisualElement, "Key", "key", "key_up")
|
VisualElement.registerEventCallback(VisualElement, "Key", "key", "key_up")
|
||||||
@@ -210,6 +210,9 @@ end
|
|||||||
--- @param y number The y position to check
|
--- @param y number The y position to check
|
||||||
--- @return boolean isInBounds Whether the coordinates are within the bounds of the element
|
--- @return boolean isInBounds Whether the coordinates are within the bounds of the element
|
||||||
function VisualElement:isInBounds(x, y)
|
function VisualElement:isInBounds(x, y)
|
||||||
|
if x == nil or y == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
local xPos, yPos = self.get("x"), self.get("y")
|
local xPos, yPos = self.get("x"), self.get("y")
|
||||||
local width, height = self.get("width"), self.get("height")
|
local width, height = self.get("width"), self.get("height")
|
||||||
if(self.get("ignoreOffset"))then
|
if(self.get("ignoreOffset"))then
|
||||||
@@ -467,4 +470,9 @@ end
|
|||||||
function VisualElement:postRender()
|
function VisualElement:postRender()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function VisualElement:destroy()
|
||||||
|
self.set("visible", false)
|
||||||
|
BaseElement.destroy(self)
|
||||||
|
end
|
||||||
|
|
||||||
return VisualElement
|
return VisualElement
|
||||||
@@ -305,12 +305,6 @@ local function renderFrames()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Renders all frames in the Basalt runtime
|
|
||||||
--- @shortDescription Renders all frames
|
|
||||||
function basalt.render()
|
|
||||||
renderFrames()
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Runs basalt once, can be used to update the UI manually, but you have to feed it the events
|
--- Runs basalt once, can be used to update the UI manually, but you have to feed it the events
|
||||||
--- @shortDescription Runs basalt once
|
--- @shortDescription Runs basalt once
|
||||||
--- @vararg any The event to run with
|
--- @vararg any The event to run with
|
||||||
|
|||||||
@@ -95,9 +95,6 @@ local function findExpressions(text)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function convertValue(value, scope)
|
local function convertValue(value, scope)
|
||||||
if type(value) ~= "string" then
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
if value:sub(1,1) == "\"" and value:sub(-1) == "\"" then
|
if value:sub(1,1) == "\"" and value:sub(-1) == "\"" then
|
||||||
value = value:sub(2, -2)
|
value = value:sub(2, -2)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user