begin major Element refactor
This commit is contained in:
@@ -1,93 +1,70 @@
|
||||
--- Utility module for parsing and resolving CSS-like units (px, %, vw, vh, ew, eh)
|
||||
--- Provides unit parsing, validation, and conversion to pixel values
|
||||
---@class Units
|
||||
---@field _Context table? Context module dependency
|
||||
---@field _ErrorHandler table? ErrorHandler module dependency
|
||||
local Units = {}
|
||||
|
||||
local Context = nil
|
||||
local ErrorHandler = nil
|
||||
|
||||
--- Initialize Units module with Context dependency
|
||||
---@param context table The Context module
|
||||
--- Initialize dependencies
|
||||
---@param deps table Dependencies: { Context = Context?, ErrorHandler = ErrorHandler? }
|
||||
--- Initialize Units module with dependencies
|
||||
---@param deps table Dependencies: { Context = table?, ErrorHandler = table? }
|
||||
function Units.init(deps)
|
||||
if type(deps) == "table" then
|
||||
if deps.Context then
|
||||
Context = deps.Context
|
||||
end
|
||||
if deps.ErrorHandler then
|
||||
ErrorHandler = deps.ErrorHandler
|
||||
end
|
||||
end
|
||||
Units._Context = deps.Context
|
||||
Units._ErrorHandler = deps.ErrorHandler
|
||||
end
|
||||
|
||||
---@param value string|number
|
||||
---@return number, string -- Returns numeric value and unit type ("px", "%", "vw", "vh")
|
||||
--- Parse a unit value into numeric value and unit type
|
||||
--- Supports: px (pixels), % (percentage), vw/vh (viewport), ew/eh (element)
|
||||
---@param value string|number The value to parse (e.g., "50px", "10%", "2vw", 100)
|
||||
---@return number numericValue The numeric portion of the value
|
||||
---@return string unitType The unit type ("px", "%", "vw", "vh", "ew", "eh")
|
||||
function Units.parse(value)
|
||||
if type(value) == "number" then
|
||||
return value, "px"
|
||||
end
|
||||
|
||||
if type(value) ~= "string" then
|
||||
if ErrorHandler then
|
||||
ErrorHandler.warn("Units", "VAL_001", "Invalid property type", {
|
||||
property = "unit value",
|
||||
expected = "string or number",
|
||||
got = type(value)
|
||||
}, "Using fallback: 0px")
|
||||
else
|
||||
print(string.format("[FlexLove - Units] Warning: Invalid unit value type. Expected string or number, got %s. Using fallback: 0px", type(value)))
|
||||
end
|
||||
Units._ErrorHandler:warn("Units", "VAL_001", "Invalid property type", {
|
||||
property = "unit value",
|
||||
expected = "string or number",
|
||||
got = type(value),
|
||||
}, "Using fallback: 0px")
|
||||
return 0, "px"
|
||||
end
|
||||
|
||||
-- Check for unit-only input (e.g., "px", "%", "vw" without a number)
|
||||
local validUnits = { px = true, ["%"] = true, vw = true, vh = true, ew = true, eh = true }
|
||||
if validUnits[value] then
|
||||
if ErrorHandler then
|
||||
ErrorHandler.warn("Units", "VAL_005", "Invalid unit format", {
|
||||
input = value,
|
||||
expected = "number + unit (e.g., '50" .. value .. "')"
|
||||
}, string.format("Add a numeric value before '%s', like '50%s'. Using fallback: 0px", value, value))
|
||||
else
|
||||
print(string.format("[FlexLove - Units] Warning: Missing numeric value before unit '%s'. Use format like '50%s'. Using fallback: 0px", value, value))
|
||||
end
|
||||
Units._ErrorHandler:warn("Units", "VAL_005", "Invalid unit format", {
|
||||
input = value,
|
||||
expected = "number + unit (e.g., '50" .. value .. "')",
|
||||
}, string.format("Add a numeric value before '%s', like '50%s'. Using fallback: 0px", value, value))
|
||||
return 0, "px"
|
||||
end
|
||||
|
||||
-- Check for invalid format (space between number and unit)
|
||||
if value:match("%d%s+%a") then
|
||||
if ErrorHandler then
|
||||
ErrorHandler.warn("Units", "VAL_005", "Invalid unit format", {
|
||||
input = value,
|
||||
issue = "contains space between number and unit"
|
||||
}, "Remove spaces: use '50px' not '50 px'. Using fallback: 0px")
|
||||
else
|
||||
print(string.format("[FlexLove - Units] Warning: Invalid unit string '%s' (contains space). Use format like '50px' or '50%%'. Using fallback: 0px", value))
|
||||
end
|
||||
Units._ErrorHandler:warn("Units", "VAL_005", "Invalid unit format", {
|
||||
input = value,
|
||||
issue = "contains space between number and unit",
|
||||
}, "Remove spaces: use '50px' not '50 px'. Using fallback: 0px")
|
||||
return 0, "px"
|
||||
end
|
||||
|
||||
-- Match number followed by optional unit
|
||||
local numStr, unit = value:match("^([%-]?[%d%.]+)(.*)$")
|
||||
if not numStr then
|
||||
if ErrorHandler then
|
||||
ErrorHandler.warn("Units", "VAL_005", "Invalid unit format", {
|
||||
input = value
|
||||
}, "Expected format: number + unit (e.g., '50px', '10%', '2vw'). Using fallback: 0px")
|
||||
else
|
||||
print(string.format("[FlexLove - Units] Warning: Invalid unit format '%s'. Expected format: number + unit (e.g., '50px', '10%%', '2vw'). Using fallback: 0px", value))
|
||||
end
|
||||
Units._ErrorHandler:warn("Units", "VAL_005", "Invalid unit format", {
|
||||
input = value,
|
||||
}, "Expected format: number + unit (e.g., '50px', '10%', '2vw'). Using fallback: 0px")
|
||||
return 0, "px"
|
||||
end
|
||||
|
||||
local num = tonumber(numStr)
|
||||
if not num then
|
||||
if ErrorHandler then
|
||||
ErrorHandler.warn("Units", "VAL_005", "Invalid unit format", {
|
||||
input = value,
|
||||
issue = "numeric value cannot be parsed"
|
||||
}, "Using fallback: 0px")
|
||||
else
|
||||
print(string.format("[FlexLove - Units] Warning: Invalid numeric value in '%s'. Using fallback: 0px", value))
|
||||
end
|
||||
Units._ErrorHandler:warn("Units", "VAL_005", "Invalid unit format", {
|
||||
input = value,
|
||||
issue = "numeric value cannot be parsed",
|
||||
}, "Using fallback: 0px")
|
||||
return 0, "px"
|
||||
end
|
||||
|
||||
@@ -98,42 +75,35 @@ function Units.parse(value)
|
||||
|
||||
-- validUnits is already defined at the top of the function
|
||||
if not validUnits[unit] then
|
||||
if ErrorHandler then
|
||||
ErrorHandler.warn("Units", "VAL_005", "Invalid unit format", {
|
||||
input = value,
|
||||
unit = unit,
|
||||
validUnits = "px, %, vw, vh, ew, eh"
|
||||
}, string.format("Treating '%s' as pixels", value))
|
||||
else
|
||||
print(string.format("[FlexLove - Units] Warning: Unknown unit '%s' in '%s'. Valid units: px, %%, vw, vh, ew, eh. Treating as pixels", unit, value))
|
||||
end
|
||||
Units._ErrorHandler:warn("Units", "VAL_005", "Invalid unit format", {
|
||||
input = value,
|
||||
unit = unit,
|
||||
validUnits = "px, %, vw, vh, ew, eh",
|
||||
}, string.format("Treating '%s' as pixels", value))
|
||||
return num, "px"
|
||||
end
|
||||
|
||||
return num, unit
|
||||
end
|
||||
|
||||
--- Convert relative units to pixels based on viewport and parent dimensions
|
||||
---@param value number -- Numeric value to convert
|
||||
---@param unit string -- Unit type ("px", "%", "vw", "vh", "ew", "eh")
|
||||
---@param viewportWidth number -- Current viewport width in pixels
|
||||
---@param viewportHeight number -- Current viewport height in pixels
|
||||
---@param parentSize number? -- Required for percentage units (parent dimension)
|
||||
---@return number -- Resolved pixel value
|
||||
---@throws Error if unit type is unknown or percentage used without parent size
|
||||
--- Convert relative units to absolute pixel values
|
||||
--- Resolves %, vw, vh units based on viewport and parent dimensions
|
||||
---@param value number Numeric value to convert
|
||||
---@param unit string Unit type ("px", "%", "vw", "vh", "ew", "eh")
|
||||
---@param viewportWidth number Current viewport width in pixels
|
||||
---@param viewportHeight number Current viewport height in pixels
|
||||
---@param parentSize number? Required for percentage units (parent dimension in pixels)
|
||||
---@return number resolvedValue Resolved pixel value
|
||||
function Units.resolve(value, unit, viewportWidth, viewportHeight, parentSize)
|
||||
if unit == "px" then
|
||||
return value
|
||||
elseif unit == "%" then
|
||||
if not parentSize then
|
||||
if ErrorHandler then
|
||||
ErrorHandler.error("Units", "LAY_003", "Invalid dimensions", {
|
||||
unit = "%",
|
||||
issue = "parent dimension not available"
|
||||
}, "Percentage units require a parent element with explicit dimensions")
|
||||
else
|
||||
error("Percentage units require parent dimension")
|
||||
end
|
||||
Units._ErrorHandler:warn("Units", "LAY_003", "Invalid dimensions", {
|
||||
unit = "%",
|
||||
issue = "parent dimension not available",
|
||||
}, "Percentage units require a parent element with explicit dimensions. Using fallback: 0px")
|
||||
return 0
|
||||
end
|
||||
return (value / 100) * parentSize
|
||||
elseif unit == "vw" then
|
||||
@@ -141,22 +111,22 @@ function Units.resolve(value, unit, viewportWidth, viewportHeight, parentSize)
|
||||
elseif unit == "vh" then
|
||||
return (value / 100) * viewportHeight
|
||||
else
|
||||
if ErrorHandler then
|
||||
ErrorHandler.error("Units", "VAL_005", "Invalid unit format", {
|
||||
unit = unit,
|
||||
validUnits = "px, %, vw, vh, ew, eh"
|
||||
})
|
||||
else
|
||||
error(string.format("Unknown unit type: '%s'", unit))
|
||||
end
|
||||
Units._ErrorHandler:warn("Units", "VAL_005", "Invalid unit format", {
|
||||
unit = unit,
|
||||
validUnits = "px, %, vw, vh, ew, eh",
|
||||
}, string.format("Unknown unit type: '%s'. Using fallback: 0px", unit))
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
---@return number, number -- width, height
|
||||
--- Get current viewport dimensions
|
||||
--- Uses cached viewport during resize operations, otherwise queries LÖVE graphics
|
||||
---@return number width Viewport width in pixels
|
||||
---@return number height Viewport height in pixels
|
||||
function Units.getViewport()
|
||||
-- Return cached viewport if available (only during resize operations)
|
||||
if Context and Context._cachedViewport and Context._cachedViewport.width > 0 then
|
||||
return Context._cachedViewport.width, Context._cachedViewport.height
|
||||
if Units._Context._cachedViewport and Units._Context._cachedViewport.width > 0 then
|
||||
return Units._Context._cachedViewport.width, Units._Context._cachedViewport.height
|
||||
end
|
||||
|
||||
if love.graphics and love.graphics.getDimensions then
|
||||
@@ -167,10 +137,12 @@ function Units.getViewport()
|
||||
end
|
||||
end
|
||||
|
||||
---@param value number
|
||||
---@param axis "x"|"y"
|
||||
---@param scaleFactors {x:number, y:number}
|
||||
---@return number
|
||||
--- Apply base scale factor to a value based on axis
|
||||
--- Used for responsive scaling of UI elements
|
||||
---@param value number The value to scale
|
||||
---@param axis "x"|"y" The axis to scale on
|
||||
---@param scaleFactors {x:number, y:number} Scale factors for each axis
|
||||
---@return number scaledValue The scaled value
|
||||
function Units.applyBaseScale(value, axis, scaleFactors)
|
||||
if axis == "x" then
|
||||
return value * scaleFactors.x
|
||||
@@ -179,10 +151,12 @@ function Units.applyBaseScale(value, axis, scaleFactors)
|
||||
end
|
||||
end
|
||||
|
||||
---@param spacingProps table?
|
||||
---@param parentWidth number
|
||||
---@param parentHeight number
|
||||
---@return table -- Resolved spacing with top, right, bottom, left in pixels
|
||||
--- Resolve spacing properties (margin, padding) to pixel values
|
||||
--- Supports individual sides (top, right, bottom, left) and shortcuts (vertical, horizontal)
|
||||
---@param spacingProps table? Spacing properties with top/right/bottom/left/vertical/horizontal
|
||||
---@param parentWidth number Parent element width in pixels
|
||||
---@param parentHeight number Parent element height in pixels
|
||||
---@return table resolvedSpacing Table with top, right, bottom, left in pixels
|
||||
function Units.resolveSpacing(spacingProps, parentWidth, parentHeight)
|
||||
if not spacingProps then
|
||||
return { top = 0, right = 0, bottom = 0, left = 0 }
|
||||
@@ -230,8 +204,10 @@ function Units.resolveSpacing(spacingProps, parentWidth, parentHeight)
|
||||
return result
|
||||
end
|
||||
|
||||
---@param unitStr string
|
||||
---@return boolean
|
||||
--- Validate a unit string format
|
||||
--- Checks if the string can be successfully parsed as a valid unit
|
||||
---@param unitStr string The unit string to validate (e.g., "50px", "10%")
|
||||
---@return boolean isValid True if the unit string is valid, false otherwise
|
||||
function Units.isValid(unitStr)
|
||||
if type(unitStr) ~= "string" then
|
||||
return false
|
||||
@@ -264,14 +240,4 @@ function Units.isValid(unitStr)
|
||||
return validUnits[unit] == true
|
||||
end
|
||||
|
||||
---@param value string|number -- Value to parse and resolve
|
||||
---@param viewportWidth number -- Current viewport width
|
||||
---@param viewportHeight number -- Current viewport height
|
||||
---@param parentSize number? -- Parent dimension for percentage units
|
||||
---@return number -- Resolved pixel value
|
||||
function Units.parseAndResolve(value, viewportWidth, viewportHeight, parentSize)
|
||||
local numValue, unit = Units.parse(value)
|
||||
return Units.resolve(numValue, unit, viewportWidth, viewportHeight, parentSize)
|
||||
end
|
||||
|
||||
return Units
|
||||
|
||||
Reference in New Issue
Block a user