reposition based on state
This commit is contained in:
182
FlexLove.lua
182
FlexLove.lua
@@ -2656,13 +2656,46 @@ function Element.new(props)
|
|||||||
-- For auto-sized elements, this is content width; for explicit sizing, this is border-box width
|
-- For auto-sized elements, this is content width; for explicit sizing, this is border-box width
|
||||||
local tempPadding
|
local tempPadding
|
||||||
if use9PatchPadding then
|
if use9PatchPadding then
|
||||||
-- Use 9-patch content padding directly (no need to resolve, it's already in pixels)
|
-- Scale 9-patch content padding to match the actual rendered size
|
||||||
tempPadding = {
|
-- The contentPadding values are in the original image's pixel coordinates,
|
||||||
left = ninePatchContentPadding.left,
|
-- but we need to scale them proportionally to the element's actual size
|
||||||
top = ninePatchContentPadding.top,
|
local themeToUse = self.theme and themes[self.theme] or Theme.getActive()
|
||||||
right = ninePatchContentPadding.right,
|
if themeToUse and themeToUse.components[self.themeComponent] then
|
||||||
bottom = ninePatchContentPadding.bottom,
|
local component = themeToUse.components[self.themeComponent]
|
||||||
}
|
local atlasImage = component._loadedAtlas or themeToUse.atlas
|
||||||
|
|
||||||
|
if atlasImage and type(atlasImage) ~= "string" then
|
||||||
|
local originalWidth, originalHeight = atlasImage:getDimensions()
|
||||||
|
|
||||||
|
-- Calculate the scale factor based on the element's border-box size vs original image size
|
||||||
|
-- For explicit sizing, tempWidth/tempHeight represent the border-box dimensions
|
||||||
|
local scaleX = tempWidth / originalWidth
|
||||||
|
local scaleY = tempHeight / originalHeight
|
||||||
|
|
||||||
|
tempPadding = {
|
||||||
|
left = ninePatchContentPadding.left * scaleX,
|
||||||
|
top = ninePatchContentPadding.top * scaleY,
|
||||||
|
right = ninePatchContentPadding.right * scaleX,
|
||||||
|
bottom = ninePatchContentPadding.bottom * scaleY,
|
||||||
|
}
|
||||||
|
else
|
||||||
|
-- Fallback if atlas image not available
|
||||||
|
tempPadding = {
|
||||||
|
left = ninePatchContentPadding.left,
|
||||||
|
top = ninePatchContentPadding.top,
|
||||||
|
right = ninePatchContentPadding.right,
|
||||||
|
bottom = ninePatchContentPadding.bottom,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Fallback if theme not found
|
||||||
|
tempPadding = {
|
||||||
|
left = ninePatchContentPadding.left,
|
||||||
|
top = ninePatchContentPadding.top,
|
||||||
|
right = ninePatchContentPadding.right,
|
||||||
|
bottom = ninePatchContentPadding.bottom,
|
||||||
|
}
|
||||||
|
end
|
||||||
else
|
else
|
||||||
tempPadding = Units.resolveSpacing(props.padding, self.width, self.height)
|
tempPadding = Units.resolveSpacing(props.padding, self.width, self.height)
|
||||||
end
|
end
|
||||||
@@ -3119,6 +3152,109 @@ function Element:getBorderBoxHeight()
|
|||||||
return self._borderBoxHeight or (self.height + self.padding.top + self.padding.bottom)
|
return self._borderBoxHeight or (self.height + self.padding.top + self.padding.bottom)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get the current state's scaled content padding
|
||||||
|
--- Returns the contentPadding for the current theme state, scaled to the element's size
|
||||||
|
---@return table|nil -- {left, top, right, bottom} or nil if no contentPadding
|
||||||
|
function Element:getScaledContentPadding()
|
||||||
|
if not self.themeComponent then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local themeToUse = self.theme and themes[self.theme] or Theme.getActive()
|
||||||
|
if not themeToUse or not themeToUse.components[self.themeComponent] then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local component = themeToUse.components[self.themeComponent]
|
||||||
|
|
||||||
|
-- Check for state-specific override
|
||||||
|
local state = self._themeState or "normal"
|
||||||
|
if state and state ~= "normal" and component.states and component.states[state] then
|
||||||
|
component = component.states[state]
|
||||||
|
end
|
||||||
|
|
||||||
|
if not component._ninePatchData or not component._ninePatchData.contentPadding then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local contentPadding = component._ninePatchData.contentPadding
|
||||||
|
|
||||||
|
-- Scale contentPadding to match the actual rendered size
|
||||||
|
local atlasImage = component._loadedAtlas or themeToUse.atlas
|
||||||
|
if atlasImage and type(atlasImage) ~= "string" then
|
||||||
|
local originalWidth, originalHeight = atlasImage:getDimensions()
|
||||||
|
local borderBoxWidth = self._borderBoxWidth or (self.width + self.padding.left + self.padding.right)
|
||||||
|
local borderBoxHeight = self._borderBoxHeight or (self.height + self.padding.top + self.padding.bottom)
|
||||||
|
local scaleX = borderBoxWidth / originalWidth
|
||||||
|
local scaleY = borderBoxHeight / originalHeight
|
||||||
|
|
||||||
|
return {
|
||||||
|
left = contentPadding.left * scaleX,
|
||||||
|
top = contentPadding.top * scaleY,
|
||||||
|
right = contentPadding.right * scaleX,
|
||||||
|
bottom = contentPadding.bottom * scaleY,
|
||||||
|
}
|
||||||
|
else
|
||||||
|
-- Return unscaled values as fallback
|
||||||
|
return {
|
||||||
|
left = contentPadding.left,
|
||||||
|
top = contentPadding.top,
|
||||||
|
right = contentPadding.right,
|
||||||
|
bottom = contentPadding.bottom,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get available content width for children (accounting for 9-slice content padding)
|
||||||
|
--- This is the width that children should use when calculating percentage widths
|
||||||
|
---@return number
|
||||||
|
function Element:getAvailableContentWidth()
|
||||||
|
local availableWidth = self.width
|
||||||
|
|
||||||
|
local scaledContentPadding = self:getScaledContentPadding()
|
||||||
|
if scaledContentPadding then
|
||||||
|
-- Check if the element is using the scaled 9-patch contentPadding as its padding
|
||||||
|
-- Allow small floating point differences (within 0.1 pixels)
|
||||||
|
local usingContentPaddingAsPadding = (
|
||||||
|
math.abs(self.padding.left - scaledContentPadding.left) < 0.1
|
||||||
|
and math.abs(self.padding.right - scaledContentPadding.right) < 0.1
|
||||||
|
)
|
||||||
|
|
||||||
|
if not usingContentPaddingAsPadding then
|
||||||
|
-- Element has explicit padding different from contentPadding
|
||||||
|
-- Subtract scaled contentPadding to get the area children should use
|
||||||
|
availableWidth = availableWidth - scaledContentPadding.left - scaledContentPadding.right
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return math.max(0, availableWidth)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get available content height for children (accounting for 9-slice content padding)
|
||||||
|
--- This is the height that children should use when calculating percentage heights
|
||||||
|
---@return number
|
||||||
|
function Element:getAvailableContentHeight()
|
||||||
|
local availableHeight = self.height
|
||||||
|
|
||||||
|
local scaledContentPadding = self:getScaledContentPadding()
|
||||||
|
if scaledContentPadding then
|
||||||
|
-- Check if the element is using the scaled 9-patch contentPadding as its padding
|
||||||
|
-- Allow small floating point differences (within 0.1 pixels)
|
||||||
|
local usingContentPaddingAsPadding = (
|
||||||
|
math.abs(self.padding.top - scaledContentPadding.top) < 0.1
|
||||||
|
and math.abs(self.padding.bottom - scaledContentPadding.bottom) < 0.1
|
||||||
|
)
|
||||||
|
|
||||||
|
if not usingContentPaddingAsPadding then
|
||||||
|
-- Element has explicit padding different from contentPadding
|
||||||
|
-- Subtract scaled contentPadding to get the area children should use
|
||||||
|
availableHeight = availableHeight - scaledContentPadding.top - scaledContentPadding.bottom
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return math.max(0, availableHeight)
|
||||||
|
end
|
||||||
|
|
||||||
--- Add child to element
|
--- Add child to element
|
||||||
---@param child Element
|
---@param child Element
|
||||||
function Element:addChild(child)
|
function Element:addChild(child)
|
||||||
@@ -3836,18 +3972,38 @@ function Element:draw()
|
|||||||
local textWidth = font:getWidth(self.text)
|
local textWidth = font:getWidth(self.text)
|
||||||
local textHeight = font:getHeight()
|
local textHeight = font:getHeight()
|
||||||
local tx, ty
|
local tx, ty
|
||||||
|
|
||||||
-- Text is drawn in the content box (inside padding)
|
-- Text is drawn in the content box (inside padding)
|
||||||
local contentX = self.x + self.padding.left
|
-- For 9-slice components, use contentPadding if available
|
||||||
local contentY = self.y + self.padding.top
|
local textPaddingLeft = self.padding.left
|
||||||
|
local textPaddingTop = self.padding.top
|
||||||
|
local textAreaWidth = self.width
|
||||||
|
local textAreaHeight = self.height
|
||||||
|
|
||||||
|
-- Check if we should use 9-slice contentPadding for text positioning
|
||||||
|
local scaledContentPadding = self:getScaledContentPadding()
|
||||||
|
if scaledContentPadding then
|
||||||
|
local borderBoxWidth = self._borderBoxWidth or (self.width + self.padding.left + self.padding.right)
|
||||||
|
local borderBoxHeight = self._borderBoxHeight or (self.height + self.padding.top + self.padding.bottom)
|
||||||
|
|
||||||
|
textPaddingLeft = scaledContentPadding.left
|
||||||
|
textPaddingTop = scaledContentPadding.top
|
||||||
|
textAreaWidth = borderBoxWidth - scaledContentPadding.left - scaledContentPadding.right
|
||||||
|
textAreaHeight = borderBoxHeight - scaledContentPadding.top - scaledContentPadding.bottom
|
||||||
|
end
|
||||||
|
|
||||||
|
local contentX = self.x + textPaddingLeft
|
||||||
|
local contentY = self.y + textPaddingTop
|
||||||
|
|
||||||
if self.textAlign == TextAlign.START then
|
if self.textAlign == TextAlign.START then
|
||||||
tx = contentX
|
tx = contentX
|
||||||
ty = contentY
|
ty = contentY
|
||||||
elseif self.textAlign == TextAlign.CENTER then
|
elseif self.textAlign == TextAlign.CENTER then
|
||||||
tx = contentX + (self.width - textWidth) / 2
|
tx = contentX + (textAreaWidth - textWidth) / 2
|
||||||
ty = contentY + (self.height - textHeight) / 2
|
ty = contentY + (textAreaHeight - textHeight) / 2
|
||||||
elseif self.textAlign == TextAlign.END then
|
elseif self.textAlign == TextAlign.END then
|
||||||
tx = contentX + self.width - textWidth - 10
|
tx = contentX + textAreaWidth - textWidth - 10
|
||||||
ty = contentY + self.height - textHeight - 10
|
ty = contentY + textAreaHeight - textHeight - 10
|
||||||
elseif self.textAlign == TextAlign.JUSTIFY then
|
elseif self.textAlign == TextAlign.JUSTIFY then
|
||||||
--- need to figure out spreading
|
--- need to figure out spreading
|
||||||
tx = contentX
|
tx = contentX
|
||||||
|
|||||||
Reference in New Issue
Block a user