Skip to content

Commit 15a9995

Browse files
committed
IsInBounds Fix
1 parent 2a23bc0 commit 15a9995

File tree

9 files changed

+128
-92
lines changed

9 files changed

+128
-92
lines changed

src/elements/BaseElement.lua

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -259,15 +259,12 @@ end
259259
--- Destroys the element and cleans up all references
260260
--- @shortDescription Destroys the element and cleans up all references
261261
function BaseElement:destroy()
262-
self._destroyed = true
263-
self:removeAllObservers()
264-
self:setFocused(false)
265-
for event in pairs(self._registeredEvents) do
266-
self:listenEvent(event, false)
267-
end
268262
if(self.parent) then
269263
self.parent:removeChild(self)
270264
end
265+
self._destroyed = true
266+
self:removeAllObservers()
267+
self:setFocused(false)
271268
end
272269

273270
--- Requests a render update for this element

src/elements/Container.lua

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ local function sortAndFilterChildren(self, children)
164164
local visibleChildren = {}
165165

166166
for _, child in ipairs(children) do
167-
if self:isChildVisible(child) and child.get("visible") then
167+
if self:isChildVisible(child) and child.get("visible") and not child._destroyed then
168168
table.insert(visibleChildren, child)
169169
end
170170
end
@@ -250,7 +250,7 @@ function Container:registerChildEvent(child, eventName)
250250
end
251251

252252
for _, registeredChild in ipairs(self._values.childrenEvents[eventName]) do
253-
if registeredChild == child then
253+
if registeredChild.get("id") == child.get("id") then
254254
return self
255255
end
256256
end
@@ -347,13 +347,11 @@ end
347347

348348
local function convertMousePosition(self, event, ...)
349349
local args = {...}
350-
if event then
351-
if event:find("mouse_") then
352-
local button, absX, absY = ...
353-
local xOffset, yOffset = self.get("offsetX"), self.get("offsetY")
354-
local relX, relY = self:getRelativePosition(absX + xOffset, absY + yOffset)
355-
args = {button, relX, relY}
356-
end
350+
if event:find("mouse_") then
351+
local button, absX, absY = ...
352+
local xOffset, yOffset = self.get("offsetX"), self.get("offsetY")
353+
local relX, relY = self:getRelativePosition(absX + xOffset, absY + yOffset)
354+
args = {button, relX, relY}
357355
end
358356
return args
359357
end
@@ -488,13 +486,10 @@ end
488486
--- @return boolean handled Whether the event was handled
489487
--- @protected
490488
function Container:mouse_scroll(direction, x, y)
491-
local args = convertMousePosition(self, "mouse_scroll", direction, x, y)
492-
local success, child = self:callChildrenEvent(true, "mouse_scroll", table.unpack(args))
493-
if(success)then
494-
return true
495-
end
496489
if(VisualElement.mouse_scroll(self, direction, x, y))then
497-
return true
490+
local args = convertMousePosition(self, "mouse_scroll", direction, x, y)
491+
local success, child = self:callChildrenEvent(true, "mouse_scroll", table.unpack(args))
492+
return success
498493
end
499494
return false
500495
end
@@ -690,10 +685,6 @@ end
690685
--- @private
691686
function Container:destroy()
692687
if not self:isType("BaseFrame") then
693-
for _, child in ipairs(self.get("children")) do
694-
child:destroy()
695-
end
696-
self.set("childrenSorted", false)
697688
VisualElement.destroy(self)
698689
return self
699690
else

src/elements/Flexbox.lua

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,6 @@ function Flexbox:addChild(element)
787787
return self
788788
end
789789

790-
--- Removes a child element from the flexbox
791790
--- @shortDescription Removes a child element from the flexbox
792791
--- @param element Element The child element to remove
793792
--- @return Flexbox self The flexbox instance

src/elements/Frame.lua

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ Frame.defineProperty(Frame, "draggable", {default = false, type = "boolean", set
1919
end})
2020
---@property draggingMap table {} The map of dragging positions
2121
Frame.defineProperty(Frame, "draggingMap", {default = {{x=1, y=1, width="width", height=1}}, type = "table"})
22+
---@property scrollable boolean false Whether the frame is scrollable
23+
Frame.defineProperty(Frame, "scrollable", {default = false, type = "boolean", setter=function(self, value)
24+
if value then
25+
self:listenEvent("mouse_scroll", true)
26+
end
27+
return value
28+
end})
2229

2330
--- Creates a new Frame instance
2431
--- @shortDescription Creates a new Frame instance
@@ -94,9 +101,12 @@ end
94101
--- @return boolean handled Whether the event was handled
95102
--- @protected
96103
function Frame:mouse_up(button, x, y)
97-
self.dragging = false
98-
self.dragStartX = nil
99-
self.dragStartY = nil
104+
if self.dragging then
105+
self.dragging = false
106+
self.dragStartX = nil
107+
self.dragStartY = nil
108+
return true
109+
end
100110
return Container.mouse_up(self, button, x, y)
101111
end
102112

@@ -121,4 +131,58 @@ function Frame:mouse_drag(button, x, y)
121131
return false
122132
end
123133

134+
--- @shortDescription Calculates the total height of all children elements
135+
--- @return number height The total height needed for all children
136+
--- @protected
137+
function Frame:getChildrenHeight()
138+
local maxHeight = 0
139+
local children = self.get("children")
140+
141+
for _, child in ipairs(children) do
142+
if child.get("visible") then
143+
local childY = child.get("y")
144+
local childHeight = child.get("height")
145+
local totalHeight = childY + childHeight - 1
146+
147+
if totalHeight > maxHeight then
148+
maxHeight = totalHeight
149+
end
150+
end
151+
end
152+
153+
return maxHeight
154+
end
155+
156+
--- @shortDescription Handles mouse scroll events
157+
--- @param direction number The scroll direction
158+
--- @param x number The x position of the scroll
159+
--- @param y number The y position of the scroll
160+
--- @return boolean handled Whether the event was handled
161+
--- @protected
162+
function Frame:mouse_scroll(direction, x, y)
163+
if Container.mouse_scroll(self, direction, x, y) then
164+
return true
165+
end
166+
167+
if self.get("scrollable") then
168+
local relX, relY = self:getRelativePosition(x, y)
169+
local width = self.get("width")
170+
local height = self.get("height")
171+
172+
if relX >= 1 and relX <= width and relY >= 1 and relY <= height then
173+
local childrenHeight = self:getChildrenHeight()
174+
local currentOffset = self.get("offsetY")
175+
local maxScroll = math.max(0, childrenHeight - height)
176+
177+
local newOffset = currentOffset + direction
178+
newOffset = math.max(0, math.min(maxScroll, newOffset))
179+
180+
self.set("offsetY", newOffset)
181+
return true
182+
end
183+
end
184+
185+
return false
186+
end
187+
124188
return Frame

src/elements/List.lua

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -173,38 +173,6 @@ function List:mouse_scroll(direction, x, y)
173173
return false
174174
end
175175

176-
--- Selects an item by index
177-
--- @shortDescription Selects an item by index
178-
--- @param index number The index of the item to select
179-
--- @return List self The List instance
180-
function List:selectItem(index)
181-
local items = self.get("items")
182-
183-
if not self.get("multiSelection") then
184-
for _, item in ipairs(items) do
185-
if type(item) == "table" then
186-
item.selected = false
187-
end
188-
end
189-
end
190-
191-
local item = items[index]
192-
if type(item) == "string" then
193-
item = {text = item}
194-
items[index] = item
195-
end
196-
197-
item.selected = true
198-
199-
if item.callback then
200-
item.callback(self)
201-
end
202-
203-
self:fireEvent("select", index, item)
204-
self:updateRender()
205-
return self
206-
end
207-
208176
--- Registers a callback for the select event
209177
--- @shortDescription Registers a callback for the select event
210178
--- @param callback function The callback function to register

src/elements/Table.lua

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@ Table.defineProperty(Table, "columns", {default = {}, type = "table", canTrigger
2323
return t
2424
end})
2525
---@property data table {} The table data as array of row arrays
26-
Table.defineProperty(Table, "data", {default = {}, type = "table", canTriggerRender = true})
26+
Table.defineProperty(Table, "data", {default = {}, type = "table", canTriggerRender = true, setter=function(self, value)
27+
self.set("scrollOffset", 0)
28+
self.set("selectedRow", nil)
29+
self.set("sortColumn", nil)
30+
self.set("sortDirection", "asc")
31+
return value
32+
end})
2733
---@property selectedRow number? nil Currently selected row index
2834
Table.defineProperty(Table, "selectedRow", {default = nil, type = "number", canTriggerRender = true})
2935
---@property headerColor color blue Color of the column headers
@@ -33,9 +39,9 @@ Table.defineProperty(Table, "selectedColor", {default = colors.lightBlue, type =
3339
---@property gridColor color gray Color of grid lines
3440
Table.defineProperty(Table, "gridColor", {default = colors.gray, type = "color"})
3541
---@property sortColumn number? nil Currently sorted column index
36-
Table.defineProperty(Table, "sortColumn", {default = nil, type = "number"})
42+
Table.defineProperty(Table, "sortColumn", {default = nil, type = "number", canTriggerRender = true})
3743
---@property sortDirection string "asc" Sort direction ("asc" or "desc")
38-
Table.defineProperty(Table, "sortDirection", {default = "asc", type = "string"})
44+
Table.defineProperty(Table, "sortDirection", {default = "asc", type = "string", canTriggerRender = true})
3945
---@property scrollOffset number 0 Current scroll position
4046
Table.defineProperty(Table, "scrollOffset", {default = 0, type = "number", canTriggerRender = true})
4147

@@ -144,17 +150,11 @@ function Table:mouse_click(button, x, y)
144150
if relY > 1 then
145151
local rowIndex = relY - 2 + self.get("scrollOffset")
146152
if rowIndex >= 0 and rowIndex < #self.get("data") then
147-
local newIndex = rowIndex + 1
148-
self.set("selectedRow", newIndex)
149-
self:fireEvent("select", newIndex, self.get("data")[newIndex])
153+
self.set("selectedRow", rowIndex + 1)
150154
end
151155
end
152-
return true
153-
end
154156

155-
function Table:onSelect(callback)
156-
self:registerCallback("select", callback)
157-
return self
157+
return true
158158
end
159159

160160
--- @shortDescription Handles scrolling through the table data
@@ -168,7 +168,7 @@ function Table:mouse_scroll(direction, x, y)
168168
local data = self.get("data")
169169
local height = self.get("height")
170170
local visibleRows = height - 2
171-
local maxScroll = math.max(0, #data - visibleRows + 1)
171+
local maxScroll = math.max(0, #data - visibleRows - 1)
172172
local newOffset = math.min(maxScroll, math.max(0, self.get("scrollOffset") + direction))
173173

174174
self.set("scrollOffset", newOffset)
@@ -189,14 +189,31 @@ function Table:render()
189189
local height = self.get("height")
190190
local width = self.get("width")
191191

192+
local totalWidth = 0
193+
local lastVisibleColumn = #columns
194+
for i, col in ipairs(columns) do
195+
if totalWidth + col.width > width then
196+
if i == 1 then
197+
col.visibleWidth = width
198+
else
199+
col.visibleWidth = width - totalWidth
200+
lastVisibleColumn = i
201+
end
202+
break
203+
end
204+
col.visibleWidth = col.width
205+
totalWidth = totalWidth + col.width
206+
end
207+
192208
local currentX = 1
193209
for i, col in ipairs(columns) do
210+
if i > lastVisibleColumn then break end
194211
local text = col.name
195212
if i == sortCol then
196213
text = text .. (self.get("sortDirection") == "asc" and "\30" or "\31")
197214
end
198-
self:textFg(currentX, 1, text:sub(1, col.width), self.get("headerColor"))
199-
currentX = currentX + col.width
215+
self:textFg(currentX, 1, text:sub(1, col.visibleWidth), self.get("headerColor"))
216+
currentX = currentX + col.visibleWidth
200217
end
201218

202219
for y = 2, height do
@@ -208,17 +225,18 @@ function Table:render()
208225
local bg = (rowIndex + 1) == selected and self.get("selectedColor") or self.get("background")
209226

210227
for i, col in ipairs(columns) do
228+
if i > lastVisibleColumn then break end
211229
local cellText = tostring(rowData[i] or "")
212-
local paddedText = cellText .. string.rep(" ", col.width - #cellText)
213-
if i < #columns then
214-
paddedText = string.sub(paddedText, 1, col.width - 1) .. " "
230+
local paddedText = cellText .. string.rep(" ", col.visibleWidth - #cellText)
231+
if i < lastVisibleColumn then
232+
paddedText = string.sub(paddedText, 1, col.visibleWidth - 1) .. " "
215233
end
216-
local finalText = string.sub(paddedText, 1, col.width)
217-
local finalForeground = string.rep(tHex[self.get("foreground")], #finalText)
218-
local finalBackground = string.rep(tHex[bg], #finalText)
234+
local finalText = string.sub(paddedText, 1, col.visibleWidth)
235+
local finalForeground = string.rep(tHex[self.get("foreground")], col.visibleWidth)
236+
local finalBackground = string.rep(tHex[bg], col.visibleWidth)
219237

220238
self:blit(currentX, y, finalText, finalForeground, finalBackground)
221-
currentX = currentX + col.width
239+
currentX = currentX + col.visibleWidth
222240
end
223241
else
224242
self:blit(1, y, string.rep(" ", self.get("width")),

src/elements/VisualElement.lua

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ VisualElement.registerEventCallback(VisualElement, "ClickUp", "mouse_up", "mouse
9999
VisualElement.registerEventCallback(VisualElement, "Drag", "mouse_drag", "mouse_click", "mouse_up")
100100
VisualElement.registerEventCallback(VisualElement, "Scroll", "mouse_scroll")
101101
VisualElement.registerEventCallback(VisualElement, "Enter", "mouse_enter", "mouse_move")
102-
VisualElement.registerEventCallback(VisualElement, "Leave", "mouse_leave", "mouse_move")
102+
VisualElement.registerEventCallback(VisualElement, "LeEave", "mouse_leave", "mouse_move")
103103
VisualElement.registerEventCallback(VisualElement, "Focus", "focus", "blur")
104104
VisualElement.registerEventCallback(VisualElement, "Blur", "blur", "focus")
105105
VisualElement.registerEventCallback(VisualElement, "Key", "key", "key_up")
@@ -210,6 +210,9 @@ end
210210
--- @param y number The y position to check
211211
--- @return boolean isInBounds Whether the coordinates are within the bounds of the element
212212
function VisualElement:isInBounds(x, y)
213+
if x == nil or y == nil then
214+
return false
215+
end
213216
local xPos, yPos = self.get("x"), self.get("y")
214217
local width, height = self.get("width"), self.get("height")
215218
if(self.get("ignoreOffset"))then
@@ -467,4 +470,9 @@ end
467470
function VisualElement:postRender()
468471
end
469472

473+
function VisualElement:destroy()
474+
self.set("visible", false)
475+
BaseElement.destroy(self)
476+
end
477+
470478
return VisualElement

src/main.lua

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -305,12 +305,6 @@ local function renderFrames()
305305
end
306306
end
307307

308-
--- Renders all frames in the Basalt runtime
309-
--- @shortDescription Renders all frames
310-
function basalt.render()
311-
renderFrames()
312-
end
313-
314308
--- Runs basalt once, can be used to update the UI manually, but you have to feed it the events
315309
--- @shortDescription Runs basalt once
316310
--- @vararg any The event to run with

src/plugins/xml.lua

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,6 @@ local function findExpressions(text)
9595
end
9696

9797
local function convertValue(value, scope)
98-
if type(value) ~= "string" then
99-
return value
100-
end
10198
if value:sub(1,1) == "\"" and value:sub(-1) == "\"" then
10299
value = value:sub(2, -2)
103100
end

0 commit comments

Comments
 (0)