continued refactor

This commit is contained in:
Michael Freno
2025-11-19 16:49:34 -05:00
parent 21a4a29cf1
commit 57eb52e70d
6 changed files with 139 additions and 106 deletions

View File

@@ -10,6 +10,7 @@ local Units = req("Units")
local Context = req("Context") local Context = req("Context")
---@type StateManager ---@type StateManager
local StateManager = req("StateManager") local StateManager = req("StateManager")
---@type Performance
local Performance = req("Performance") local Performance = req("Performance")
local ImageRenderer = req("ImageRenderer") local ImageRenderer = req("ImageRenderer")
local ImageScaler = req("ImageScaler") local ImageScaler = req("ImageScaler")
@@ -20,8 +21,10 @@ local Grid = req("Grid")
local InputEvent = req("InputEvent") local InputEvent = req("InputEvent")
local GestureRecognizer = req("GestureRecognizer") local GestureRecognizer = req("GestureRecognizer")
local TextEditor = req("TextEditor") local TextEditor = req("TextEditor")
---@type LayoutEngine
local LayoutEngine = req("LayoutEngine") local LayoutEngine = req("LayoutEngine")
local Renderer = req("Renderer") local Renderer = req("Renderer")
---@type EventHandler
local EventHandler = req("EventHandler") local EventHandler = req("EventHandler")
local ScrollManager = req("ScrollManager") local ScrollManager = req("ScrollManager")
---@type ErrorHandler ---@type ErrorHandler
@@ -129,6 +132,8 @@ function flexlove.init(config)
utils.init({ ErrorHandler = flexlove._ErrorHandler }) utils.init({ ErrorHandler = flexlove._ErrorHandler })
Animation.init({ ErrorHandler = flexlove._ErrorHandler, Color = Color }) Animation.init({ ErrorHandler = flexlove._ErrorHandler, Color = Color })
Theme.init({ ErrorHandler = flexlove._ErrorHandler, Color = Color, utils = utils }) Theme.init({ ErrorHandler = flexlove._ErrorHandler, Color = Color, utils = utils })
LayoutEngine.init({ ErrorHandler = flexlove._ErrorHandler, Performance = flexlove._Performance })
EventHandler.init({ ErrorHandler = flexlove._ErrorHandler, Performance = flexlove._Performance, InputEvent = InputEvent, utils = utils })
flexlove._defaultDependencies = { flexlove._defaultDependencies = {
Context = Context, Context = Context,

View File

@@ -1369,7 +1369,8 @@ function Element.new(props)
self._layoutEngine.rowGap = self.rowGap self._layoutEngine.rowGap = self.rowGap
end end
self.transform = props.transform or {} -- transform is already set at line 424 (props.transform or nil)
-- Don't overwrite it here
self.transition = props.transition or {} self.transition = props.transition or {}
if props.overflow or props.overflowX or props.overflowY then if props.overflow or props.overflowX or props.overflowY then

View File

@@ -17,24 +17,27 @@
---@field _element Element? ---@field _element Element?
---@field _scrollbarPressHandled boolean ---@field _scrollbarPressHandled boolean
---@field _InputEvent table ---@field _InputEvent table
---@field _Context table
---@field _utils table ---@field _utils table
---@field _Performance Performance? Performance module dependency
---@field _ErrorHandler ErrorHandler
local EventHandler = {} local EventHandler = {}
EventHandler.__index = EventHandler EventHandler.__index = EventHandler
--- Create a new EventHandler instance --- Initialize module with shared dependencies
---@param deps table Dependencies {Performance, ErrorHandler, InputEvent, Context, utils}
function EventHandler.init(deps)
EventHandler._Performance = deps.Performance
EventHandler._ErrorHandler = deps.ErrorHandler
EventHandler._InputEvent = deps.InputEvent
EventHandler._utils = deps.utils
end
---@param config table Configuration options ---@param config table Configuration options
---@param deps table Dependencies {InputEvent, Context, utils}
---@return EventHandler ---@return EventHandler
function EventHandler.new(config, deps) function EventHandler.new(config)
config = config or {} config = config or {}
local self = setmetatable({}, EventHandler) local self = setmetatable({}, EventHandler)
self._InputEvent = deps.InputEvent
self._Context = deps.Context
self._utils = deps.utils
self.onEvent = config.onEvent self.onEvent = config.onEvent
self.onEventDeferred = config.onEventDeferred self.onEventDeferred = config.onEventDeferred
@@ -119,14 +122,14 @@ end
---@param isActiveElement boolean Whether this is the top element at mouse position ---@param isActiveElement boolean Whether this is the top element at mouse position
function EventHandler:processMouseEvents(mx, my, isHovering, isActiveElement) function EventHandler:processMouseEvents(mx, my, isHovering, isActiveElement)
-- Start performance timing -- Start performance timing
local Performance = package.loaded["modules.Performance"] or package.loaded["libs.modules.Performance"] -- Performance accessed via EventHandler._Performance
if Performance and Performance.isEnabled() then if EventHandler._Performance and EventHandler._Performance.enabled then
Performance.startTimer("event_mouse") EventHandler._Performance:startTimer("event_mouse")
end end
if not self._element then if not self._element then
if Performance and Performance.isEnabled() then if EventHandler._Performance and EventHandler._Performance.enabled then
Performance.stopTimer("event_mouse") EventHandler._Performance:stopTimer("event_mouse")
end end
return return
end end
@@ -166,8 +169,8 @@ function EventHandler:processMouseEvents(mx, my, isHovering, isActiveElement)
end end
end end
end end
if Performance and Performance.isEnabled() then if EventHandler._Performance and EventHandler._Performance.enabled then
Performance.stopTimer("event_mouse") EventHandler._Performance:stopTimer("event_mouse")
end end
return return
end end
@@ -221,8 +224,8 @@ function EventHandler:processMouseEvents(mx, my, isHovering, isActiveElement)
end end
-- Stop performance timing -- Stop performance timing
if Performance and Performance.isEnabled() then if EventHandler._Performance and EventHandler._Performance.enabled then
Performance.stopTimer("event_mouse") EventHandler._Performance:stopTimer("event_mouse")
end end
end end
@@ -248,8 +251,8 @@ function EventHandler:_handleMousePress(mx, my, button)
end end
-- Fire press event -- Fire press event
local modifiers = self._utils.getModifiers() local modifiers = EventHandler._utils.getModifiers()
local pressEvent = self._InputEvent.new({ local pressEvent = EventHandler._InputEvent.new({
type = "press", type = "press",
button = button, button = button,
x = mx, x = mx,
@@ -292,11 +295,11 @@ function EventHandler:_handleMouseDrag(mx, my, button, isHovering)
if lastX ~= mx or lastY ~= my then if lastX ~= mx or lastY ~= my then
-- Mouse has moved - fire drag event only if still hovering -- Mouse has moved - fire drag event only if still hovering
if isHovering then if isHovering then
local modifiers = self._utils.getModifiers() local modifiers = EventHandler._utils.getModifiers()
local dx = mx - self._dragStartX[button] local dx = mx - self._dragStartX[button]
local dy = my - self._dragStartY[button] local dy = my - self._dragStartY[button]
local dragEvent = self._InputEvent.new({ local dragEvent = EventHandler._InputEvent.new({
type = "drag", type = "drag",
button = button, button = button,
x = mx, x = mx,
@@ -332,7 +335,7 @@ function EventHandler:_handleMouseRelease(mx, my, button)
local element = self._element local element = self._element
local currentTime = love.timer.getTime() local currentTime = love.timer.getTime()
local modifiers = self._utils.getModifiers() local modifiers = EventHandler._utils.getModifiers()
-- Determine click count (double-click detection) -- Determine click count (double-click detection)
local clickCount = 1 local clickCount = 1
@@ -357,7 +360,7 @@ function EventHandler:_handleMouseRelease(mx, my, button)
end end
-- Fire click event -- Fire click event
local clickEvent = self._InputEvent.new({ local clickEvent = EventHandler._InputEvent.new({
type = eventType, type = eventType,
button = button, button = button,
x = mx, x = mx,
@@ -397,7 +400,7 @@ function EventHandler:_handleMouseRelease(mx, my, button)
end end
-- Fire release event -- Fire release event
local releaseEvent = self._InputEvent.new({ local releaseEvent = EventHandler._InputEvent.new({
type = "release", type = "release",
button = button, button = button,
x = mx, x = mx,
@@ -411,14 +414,14 @@ end
--- Process touch events in the update cycle --- Process touch events in the update cycle
function EventHandler:processTouchEvents() function EventHandler:processTouchEvents()
-- Start performance timing -- Start performance timing
local Performance = package.loaded["modules.Performance"] or package.loaded["libs.modules.Performance"] -- Performance accessed via EventHandler._Performance
if Performance and Performance.isEnabled() then if EventHandler._Performance and EventHandler._Performance.enabled then
Performance.startTimer("event_touch") EventHandler._Performance:startTimer("event_touch")
end end
if not self._element then if not self._element then
if Performance and Performance.isEnabled() then if EventHandler._Performance and EventHandler._Performance.enabled then
Performance.stopTimer("event_touch") EventHandler._Performance:stopTimer("event_touch")
end end
return return
end end
@@ -429,8 +432,8 @@ function EventHandler:processTouchEvents()
local canProcessEvents = (self.onEvent or element.editable) and not element.disabled local canProcessEvents = (self.onEvent or element.editable) and not element.disabled
if not canProcessEvents then if not canProcessEvents then
if Performance and Performance.isEnabled() then if EventHandler._Performance and EventHandler._Performance.enabled then
Performance.stopTimer("event_touch") EventHandler._Performance:stopTimer("event_touch")
end end
return return
end end
@@ -491,8 +494,8 @@ function EventHandler:processTouchEvents()
end end
-- Stop performance timing -- Stop performance timing
if Performance and Performance.isEnabled() then if EventHandler._Performance and EventHandler._Performance.enabled then
Performance.stopTimer("event_touch") EventHandler._Performance:stopTimer("event_touch")
end end
end end
@@ -525,7 +528,7 @@ function EventHandler:_handleTouchBegan(touchId, x, y, pressure)
self._touchHistory[touchId] = { { x = x, y = y, timestamp = love.timer.getTime() } } self._touchHistory[touchId] = { { x = x, y = y, timestamp = love.timer.getTime() } }
-- Create and fire touch press event -- Create and fire touch press event
local touchEvent = self._InputEvent.fromTouch(touchId, x, y, "began", pressure) local touchEvent = EventHandler._InputEvent.fromTouch(touchId, x, y, "began", pressure)
touchEvent.type = "touchpress" touchEvent.type = "touchpress"
touchEvent.dx = 0 touchEvent.dx = 0
touchEvent.dy = 0 touchEvent.dy = 0
@@ -575,7 +578,7 @@ function EventHandler:_handleTouchMoved(touchId, x, y, pressure)
self._touchHistory[touchId] = history self._touchHistory[touchId] = history
-- Create and fire touch move event -- Create and fire touch move event
local touchEvent = self._InputEvent.fromTouch(touchId, x, y, "moved", pressure) local touchEvent = EventHandler._InputEvent.fromTouch(touchId, x, y, "moved", pressure)
touchEvent.type = "touchmove" touchEvent.type = "touchmove"
touchEvent.dx = dx touchEvent.dx = dx
touchEvent.dy = dy touchEvent.dy = dy
@@ -606,7 +609,7 @@ function EventHandler:_handleTouchEnded(touchId, x, y, pressure)
local dy = y - startPos.y local dy = y - startPos.y
-- Create and fire touch release event -- Create and fire touch release event
local touchEvent = self._InputEvent.fromTouch(touchId, x, y, "ended", pressure) local touchEvent = EventHandler._InputEvent.fromTouch(touchId, x, y, "ended", pressure)
touchEvent.type = "touchrelease" touchEvent.type = "touchrelease"
touchEvent.dx = dx touchEvent.dx = dx
touchEvent.dy = dy touchEvent.dy = dy
@@ -677,11 +680,11 @@ function EventHandler:_invokeCallback(element, event)
self.onEvent(element, event) self.onEvent(element, event)
end) end)
else else
-- Fallback: execute immediately if FlexLove not available EventHandler._ErrorHandler:error("EventHandler", "SYS_003", "FlexLove.deferCallback not available", {
self.onEvent(element, event) eventType = event.type,
}, "Ensure FlexLove module is properly loaded")
end end
else else
-- Execute immediately
self.onEvent(element, event) self.onEvent(element, event)
end end
end end

View File

@@ -23,9 +23,18 @@
---@field _FlexWrap table ---@field _FlexWrap table
---@field _layoutCount number Track layout recalculations per frame ---@field _layoutCount number Track layout recalculations per frame
---@field _lastFrameCount number Last frame number for resetting counters ---@field _lastFrameCount number Last frame number for resetting counters
---@field _ErrorHandler ErrorHandler? ErrorHandler module dependency
---@field _Performance Performance? Performance module dependency
local LayoutEngine = {} local LayoutEngine = {}
LayoutEngine.__index = LayoutEngine LayoutEngine.__index = LayoutEngine
--- Initialize module with shared dependencies
---@param deps table Dependencies {ErrorHandler, Performance}
function LayoutEngine.init(deps)
LayoutEngine._ErrorHandler = deps.ErrorHandler
LayoutEngine._Performance = deps.Performance
end
---@class LayoutEngineProps ---@class LayoutEngineProps
---@field positioning Positioning? Layout positioning mode (default: RELATIVE) ---@field positioning Positioning? Layout positioning mode (default: RELATIVE)
---@field flexDirection FlexDirection? Direction of flex layout (default: HORIZONTAL) ---@field flexDirection FlexDirection? Direction of flex layout (default: HORIZONTAL)
@@ -153,10 +162,9 @@ function LayoutEngine:layoutChildren()
end end
-- Start performance timing -- Start performance timing
local Performance = package.loaded["modules.Performance"] or package.loaded["libs.modules.Performance"] if LayoutEngine._Performance and LayoutEngine._Performance.enabled then
if Performance and Performance.isEnabled() then
local elementId = self.element.id or "unnamed" local elementId = self.element.id or "unnamed"
Performance.startTimer("layout_" .. elementId) LayoutEngine._Performance:startTimer("layout_" .. elementId)
end end
-- Track layout recalculations for performance warnings -- Track layout recalculations for performance warnings
@@ -170,15 +178,15 @@ function LayoutEngine:layoutChildren()
self:applyPositioningOffsets(child) self:applyPositioningOffsets(child)
end end
end end
-- Detect overflow after children positioning -- Detect overflow after children positioning
if self.element._detectOverflow then if self.element._detectOverflow then
self.element:_detectOverflow() self.element:_detectOverflow()
end end
-- Stop performance timing -- Stop performance timing
if Performance and Performance.isEnabled() then if LayoutEngine._Performance and LayoutEngine._Performance.enabled then
Performance.stopTimer("layout_" .. (self.element.id or "unnamed")) LayoutEngine._Performance:stopTimer("layout_" .. (self.element.id or "unnamed"))
end end
return return
end end
@@ -186,10 +194,10 @@ function LayoutEngine:layoutChildren()
-- Handle grid layout -- Handle grid layout
if self.positioning == self._Positioning.GRID then if self.positioning == self._Positioning.GRID then
self._Grid.layoutGridItems(self.element) self._Grid.layoutGridItems(self.element)
-- Stop performance timing -- Stop performance timing
if Performance and Performance.isEnabled() then if LayoutEngine._Performance and LayoutEngine._Performance.enabled then
Performance.stopTimer("layout_" .. (self.element.id or "unnamed")) LayoutEngine._Performance:stopTimer("layout_" .. (self.element.id or "unnamed"))
end end
return return
end end
@@ -198,8 +206,8 @@ function LayoutEngine:layoutChildren()
if childCount == 0 then if childCount == 0 then
-- Stop performance timing -- Stop performance timing
if Performance and Performance.isEnabled() then if LayoutEngine._Performance and LayoutEngine._Performance.enabled then
Performance.stopTimer("layout_" .. (self.element.id or "unnamed")) LayoutEngine._Performance:stopTimer("layout_" .. (self.element.id or "unnamed"))
end end
return return
end end
@@ -210,20 +218,22 @@ function LayoutEngine:layoutChildren()
local isFlexChild = not (child.positioning == self._Positioning.ABSOLUTE and child._explicitlyAbsolute) local isFlexChild = not (child.positioning == self._Positioning.ABSOLUTE and child._explicitlyAbsolute)
if isFlexChild then if isFlexChild then
table.insert(flexChildren, child) table.insert(flexChildren, child)
-- Warn if child uses percentage sizing but parent has autosizing -- Warn if child uses percentage sizing but parent has autosizing
if self._ErrorHandler then if child.units and child.units.width then
if child.units and child.units.width then if child.units.width.unit == "%" and self.element.autosizing and self.element.autosizing.width then
if child.units.width.unit == "%" and self.element.autosizing and self.element.autosizing.width then LayoutEngine._ErrorHandler:warn("LayoutEngine", "LAY_004", "Invalid sizing combination", {
self._ErrorHandler.warn("LayoutEngine", child = child.id or "unnamed",
string.format("Child '%s' uses percentage width but parent has auto-sizing enabled. This may cause unexpected results", child.id or "unnamed")) issue = "percentage width with parent auto-sizing",
end }, "Use fixed or viewport units instead of percentage when parent has auto-sizing enabled")
end end
if child.units and child.units.height then end
if child.units.height.unit == "%" and self.element.autosizing and self.element.autosizing.height then if child.units and child.units.height then
self._ErrorHandler.warn("LayoutEngine", if child.units.height.unit == "%" and self.element.autosizing and self.element.autosizing.height then
string.format("Child '%s' uses percentage height but parent has auto-sizing enabled. This may cause unexpected results", child.id or "unnamed")) LayoutEngine._ErrorHandler:warn("LayoutEngine", "LAY_004", "Invalid sizing combination", {
end child = child.id or "unnamed",
issue = "percentage height with parent auto-sizing",
}, "Use fixed or viewport units instead of percentage when parent has auto-sizing enabled")
end end
end end
end end
@@ -599,10 +609,10 @@ function LayoutEngine:layoutChildren()
if self.element._detectOverflow then if self.element._detectOverflow then
self.element:_detectOverflow() self.element:_detectOverflow()
end end
-- Stop performance timing -- Stop performance timing
if Performance and Performance.isEnabled() then if LayoutEngine._Performance and LayoutEngine._Performance.enabled then
Performance.stopTimer("layout_" .. (self.element.id or "unnamed")) LayoutEngine._Performance:stopTimer("layout_" .. (self.element.id or "unnamed"))
end end
end end
@@ -977,28 +987,26 @@ end
--- Track layout recalculations and warn about excessive layouts --- Track layout recalculations and warn about excessive layouts
function LayoutEngine:_trackLayoutRecalculation() function LayoutEngine:_trackLayoutRecalculation()
-- Get Performance module if available if not LayoutEngine._Performance or not LayoutEngine._Performance.warningsEnabled then
local Performance = package.loaded["modules.Performance"] or package.loaded["libs.modules.Performance"]
if not Performance or not Performance.areWarningsEnabled() then
return return
end end
-- Get current frame count from Context -- Get current frame count from Context
local currentFrame = self._Context and self._Context._frameNumber or 0 local currentFrame = self._Context and self._Context._frameNumber or 0
-- Reset counter on new frame -- Reset counter on new frame
if currentFrame ~= self._lastFrameCount then if currentFrame ~= self._lastFrameCount then
self._lastFrameCount = currentFrame self._lastFrameCount = currentFrame
self._layoutCount = 0 self._layoutCount = 0
end end
-- Increment layout count -- Increment layout count
self._layoutCount = self._layoutCount + 1 self._layoutCount = self._layoutCount + 1
-- Warn if layout is recalculated excessively this frame -- Warn if layout is recalculated excessively this frame
if self._layoutCount >= 10 then if self._layoutCount >= 10 then
local elementId = self.element and self.element.id or "unnamed" local elementId = self.element and self.element.id or "unnamed"
Performance.logWarning( LayoutEngine._Performance:logWarning(
string.format("excessive_layout_%s", elementId), string.format("excessive_layout_%s", elementId),
"LayoutEngine", "LayoutEngine",
string.format("Layout recalculated %d times this frame for element '%s'", self._layoutCount, elementId), string.format("Layout recalculated %d times this frame for element '%s'", self._layoutCount, elementId),

View File

@@ -29,13 +29,15 @@
---@field _FONT_CACHE table ---@field _FONT_CACHE table
---@field _TextAlign table ---@field _TextAlign table
---@field _ErrorHandler ErrorHandler ---@field _ErrorHandler ErrorHandler
---@field _Performance Performance? Performance module dependency
local Renderer = {} local Renderer = {}
Renderer.__index = Renderer Renderer.__index = Renderer
--- Initialize module with shared dependencies --- Initialize module with shared dependencies
---@param deps table Dependencies {ErrorHandler} ---@param deps table Dependencies {ErrorHandler, Performance}
function Renderer.init(deps) function Renderer.init(deps)
Renderer._ErrorHandler = deps.ErrorHandler Renderer._ErrorHandler = deps.ErrorHandler
Renderer._Performance = deps.Performance
end end
--- Create a new Renderer instance --- Create a new Renderer instance
@@ -138,9 +140,23 @@ function Renderer:getBlurInstance()
quality = self.backdropBlur.quality quality = self.backdropBlur.quality
end end
-- Map string quality to numeric quality (1-10)
local numericQuality = 5 -- default medium
if type(quality) == "string" then
if quality == "low" then
numericQuality = 3
elseif quality == "medium" then
numericQuality = 5
elseif quality == "high" then
numericQuality = 8
end
elseif type(quality) == "number" then
numericQuality = quality
end
-- Create or reuse blur instance -- Create or reuse blur instance
if not self._blurInstance or self._blurInstance.quality ~= quality then if not self._blurInstance or self._blurInstance.quality ~= numericQuality then
self._blurInstance = self._Blur.new(quality) self._blurInstance = self._Blur.new({ quality = numericQuality })
end end
return self._blurInstance return self._blurInstance
@@ -344,18 +360,17 @@ end
---@param backdropCanvas table|nil Backdrop canvas for backdrop blur ---@param backdropCanvas table|nil Backdrop canvas for backdrop blur
function Renderer:draw(backdropCanvas) function Renderer:draw(backdropCanvas)
-- Start performance timing -- Start performance timing
local Performance = package.loaded["modules.Performance"] or package.loaded["libs.modules.Performance"]
local elementId local elementId
if Performance and Performance.isEnabled() and self._element then if Renderer._Performance and Renderer._Performance.enabled and self._element then
elementId = self._element.id or "unnamed" elementId = self._element.id or "unnamed"
Performance.startTimer("render_" .. elementId) Renderer._Performance:startTimer("render_" .. elementId)
Performance.incrementCounter("draw_calls", 1) Renderer._Performance:incrementCounter("draw_calls", 1)
end end
-- Early exit if element is invisible (optimization) -- Early exit if element is invisible (optimization)
if self.opacity <= 0 then if self.opacity <= 0 then
if Performance and Performance.isEnabled() and elementId then if Renderer._Performance and Renderer._Performance.enabled and elementId then
Performance.stopTimer("render_" .. elementId) Renderer._Performance:stopTimer("render_" .. elementId)
end end
return return
end end
@@ -415,8 +430,8 @@ function Renderer:draw(backdropCanvas)
end end
-- Stop performance timing -- Stop performance timing
if Performance and Performance.isEnabled() and elementId then if Renderer._Performance and Renderer._Performance.enabled and elementId then
Performance.stopTimer("render_" .. elementId) Renderer._Performance:stopTimer("render_" .. elementId)
end end
end end

View File

@@ -1,3 +1,4 @@
---@class ScrollManager ---@class ScrollManager
---@field overflow string -- "visible"|"hidden"|"auto"|"scroll" ---@field overflow string -- "visible"|"hidden"|"auto"|"scroll"
---@field overflowX string? -- X-axis specific overflow (overrides overflow) ---@field overflowX string? -- X-axis specific overflow (overrides overflow)
@@ -39,12 +40,17 @@
---@field _lastTouchY number -- Last touch Y position ---@field _lastTouchY number -- Last touch Y position
---@field _Color table ---@field _Color table
---@field _utils table ---@field _utils table
---@field _ErrorHandler table? ---@field _ErrorHandler table? ErrorHandler module dependency
local ScrollManager = {} local ScrollManager = {}
ScrollManager.__index = ScrollManager ScrollManager.__index = ScrollManager
-- Lazy-loaded ErrorHandler --- Initialize module with shared dependencies
local ErrorHandler ---@param deps table Dependencies {ErrorHandler}
function ScrollManager.init(deps)
if type(deps) == "table" then
ScrollManager._ErrorHandler = deps.ErrorHandler
end
end
--- Create a new ScrollManager instance --- Create a new ScrollManager instance
---@param config table Configuration options ---@param config table Configuration options
@@ -126,12 +132,10 @@ end
--- Detect if content overflows container bounds --- Detect if content overflows container bounds
function ScrollManager:detectOverflow() function ScrollManager:detectOverflow()
if not self._element then if not self._element then
if not ErrorHandler then ScrollManager._ErrorHandler:warn("ScrollManager", "SYS_002", "Method called before initialization", {
ErrorHandler = require("modules.ErrorHandler")
end
ErrorHandler.error("ScrollManager", "SYS_002", "Method called before initialization", {
method = "detectOverflow" method = "detectOverflow"
}, "Call scrollManager:initialize(element) before using scroll methods") }, "Call scrollManager:initialize(element) before using scroll methods")
return
end end
local element = self._element local element = self._element
@@ -258,12 +262,13 @@ end
---@return table -- {vertical: {visible, trackHeight, thumbHeight, thumbY}, horizontal: {visible, trackWidth, thumbWidth, thumbX}} ---@return table -- {vertical: {visible, trackHeight, thumbHeight, thumbY}, horizontal: {visible, trackWidth, thumbWidth, thumbX}}
function ScrollManager:calculateScrollbarDimensions() function ScrollManager:calculateScrollbarDimensions()
if not self._element then if not self._element then
if not ErrorHandler then ScrollManager._ErrorHandler:warn("ScrollManager", "SYS_002", "Method called before initialization", {
ErrorHandler = require("modules.ErrorHandler")
end
ErrorHandler.error("ScrollManager", "SYS_002", "Method called before initialization", {
method = "calculateScrollbarDimensions" method = "calculateScrollbarDimensions"
}, "Call scrollManager:initialize(element) before using scroll methods") }, "Call scrollManager:initialize(element) before using scroll methods")
return {
vertical = { visible = false, trackHeight = 0, thumbHeight = 0, thumbY = 0 },
horizontal = { visible = false, trackWidth = 0, thumbWidth = 0, thumbX = 0 },
}
end end
local element = self._element local element = self._element
@@ -356,12 +361,10 @@ end
---@return table|nil -- {component: "vertical"|"horizontal", region: "thumb"|"track"} ---@return table|nil -- {component: "vertical"|"horizontal", region: "thumb"|"track"}
function ScrollManager:getScrollbarAtPosition(mouseX, mouseY) function ScrollManager:getScrollbarAtPosition(mouseX, mouseY)
if not self._element then if not self._element then
if not ErrorHandler then ScrollManager._ErrorHandler:warn("ScrollManager", "SYS_002", "Method called before initialization", {
ErrorHandler = require("modules.ErrorHandler")
end
ErrorHandler.error("ScrollManager", "SYS_002", "Method called before initialization", {
method = "getScrollbarAtPosition" method = "getScrollbarAtPosition"
}, "Call scrollManager:initialize(element) before using scroll methods") }, "Call scrollManager:initialize(element) before using scroll methods")
return nil
end end
local element = self._element local element = self._element
@@ -430,12 +433,10 @@ end
---@return boolean -- True if event was consumed ---@return boolean -- True if event was consumed
function ScrollManager:handleMousePress(mouseX, mouseY, button) function ScrollManager:handleMousePress(mouseX, mouseY, button)
if not self._element then if not self._element then
if not ErrorHandler then ScrollManager._ErrorHandler:warn("ScrollManager", "SYS_002", "Method called before initialization", {
ErrorHandler = require("modules.ErrorHandler")
end
ErrorHandler.error("ScrollManager", "SYS_002", "Method called before initialization", {
method = "handleMousePress" method = "handleMousePress"
}, "Call scrollManager:initialize(element) before using scroll methods") }, "Call scrollManager:initialize(element) before using scroll methods")
return false
end end
if button ~= 1 then if button ~= 1 then