removed redundant methods
This commit is contained in:
@@ -2459,59 +2459,6 @@ function Element:replaceText(startPos, endPos, newText)
|
||||
end
|
||||
end
|
||||
|
||||
--- Split text into lines (for multi-line text)
|
||||
function Element:_splitLines()
|
||||
if not self.editable then
|
||||
return
|
||||
end
|
||||
|
||||
if not self.multiline then
|
||||
self._lines = { self._textBuffer or "" }
|
||||
return
|
||||
end
|
||||
|
||||
self._lines = {}
|
||||
local text = self._textBuffer or ""
|
||||
|
||||
-- Split on newlines
|
||||
for line in (text .. "\n"):gmatch("([^\n]*)\n") do
|
||||
table.insert(self._lines, line)
|
||||
end
|
||||
|
||||
-- Ensure at least one line
|
||||
if #self._lines == 0 then
|
||||
self._lines = { "" }
|
||||
end
|
||||
end
|
||||
|
||||
--- Calculate text wrapping
|
||||
function Element:_calculateWrapping()
|
||||
if not self.editable or not self.textWrap then
|
||||
self._wrappedLines = nil
|
||||
return
|
||||
end
|
||||
|
||||
self._wrappedLines = {}
|
||||
local availableWidth = self.width - self.padding.left - self.padding.right
|
||||
|
||||
for lineNum, line in ipairs(self._lines or {}) do
|
||||
if line == "" then
|
||||
table.insert(self._wrappedLines, {
|
||||
text = "",
|
||||
startIdx = 0,
|
||||
endIdx = 0,
|
||||
lineNum = lineNum,
|
||||
})
|
||||
else
|
||||
local wrappedParts = self:_wrapLine(line, availableWidth)
|
||||
for _, part in ipairs(wrappedParts) do
|
||||
part.lineNum = lineNum
|
||||
table.insert(self._wrappedLines, part)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Wrap a single line of text
|
||||
---@param line string -- Line to wrap
|
||||
---@param maxWidth number -- Maximum width in pixels
|
||||
@@ -2529,154 +2476,6 @@ end
|
||||
-- Input Handling - Mouse Selection
|
||||
-- ====================
|
||||
|
||||
--- Convert mouse coordinates to cursor position in text
|
||||
---@param mouseX number -- Mouse X coordinate (absolute)
|
||||
---@param mouseY number -- Mouse Y coordinate (absolute)
|
||||
---@return number -- Cursor position (character index)
|
||||
function Element:_mouseToTextPosition(mouseX, mouseY)
|
||||
if not self.editable or not self._textBuffer then
|
||||
return 0
|
||||
end
|
||||
|
||||
-- Get content area bounds
|
||||
local contentX = (self._absoluteX or self.x) + self.padding.left
|
||||
local contentY = (self._absoluteY or self.y) + self.padding.top
|
||||
|
||||
-- Calculate relative position within text area
|
||||
local relativeX = mouseX - contentX
|
||||
local relativeY = mouseY - contentY
|
||||
|
||||
-- Get font for measuring text
|
||||
local font = self:_getFont()
|
||||
if not font then
|
||||
return 0
|
||||
end
|
||||
|
||||
local text = self._textBuffer
|
||||
local textLength = utf8.len(text) or 0
|
||||
|
||||
-- === SINGLE-LINE TEXT HANDLING ===
|
||||
if not self.multiline then
|
||||
-- Account for horizontal scroll offset in single-line inputs
|
||||
if self._textScrollX then
|
||||
relativeX = relativeX + self._textScrollX
|
||||
end
|
||||
|
||||
-- Find the character position closest to the click
|
||||
local closestPos = 0
|
||||
local closestDist = math.huge
|
||||
|
||||
-- Check each position in the text
|
||||
for i = 0, textLength do
|
||||
-- Get text up to this position
|
||||
local offset = utf8.offset(text, i + 1)
|
||||
local beforeText = offset and text:sub(1, offset - 1) or text
|
||||
local textWidth = font:getWidth(beforeText)
|
||||
|
||||
-- Calculate distance from click to this position
|
||||
local dist = math.abs(relativeX - textWidth)
|
||||
|
||||
if dist < closestDist then
|
||||
closestDist = dist
|
||||
closestPos = i
|
||||
end
|
||||
end
|
||||
|
||||
return closestPos
|
||||
end
|
||||
|
||||
-- === MULTILINE TEXT HANDLING ===
|
||||
|
||||
-- Update text wrapping if dirty
|
||||
if self._textEditor then
|
||||
self._textEditor:_updateTextIfDirty()
|
||||
end
|
||||
|
||||
-- Split text into lines
|
||||
local lines = {}
|
||||
for line in (text .. "\n"):gmatch("([^\n]*)\n") do
|
||||
table.insert(lines, line)
|
||||
end
|
||||
if #lines == 0 then
|
||||
lines = { "" }
|
||||
end
|
||||
|
||||
local lineHeight = font:getHeight()
|
||||
|
||||
-- Get text area width for wrapping calculations
|
||||
local textAreaWidth = self.width
|
||||
local scaledContentPadding = self:getScaledContentPadding()
|
||||
if scaledContentPadding then
|
||||
local borderBoxWidth = self._borderBoxWidth or (self.width + self.padding.left + self.padding.right)
|
||||
textAreaWidth = borderBoxWidth - scaledContentPadding.left - scaledContentPadding.right
|
||||
end
|
||||
|
||||
-- Determine which line the click is on based on Y coordinate
|
||||
local clickedLineNum = math.floor(relativeY / lineHeight) + 1
|
||||
clickedLineNum = math.max(1, math.min(clickedLineNum, #lines))
|
||||
|
||||
-- Calculate character offset for lines before the clicked line
|
||||
local charOffset = 0
|
||||
for i = 1, clickedLineNum - 1 do
|
||||
local lineLen = utf8.len(lines[i]) or 0
|
||||
charOffset = charOffset + lineLen + 1 -- +1 for newline character
|
||||
end
|
||||
|
||||
-- Get the clicked line
|
||||
local clickedLine = lines[clickedLineNum]
|
||||
local lineLen = utf8.len(clickedLine) or 0
|
||||
|
||||
-- If text wrapping is enabled, handle wrapped segments
|
||||
if self.textWrap and textAreaWidth > 0 then
|
||||
local wrappedSegments = self:_wrapLine(clickedLine, textAreaWidth)
|
||||
|
||||
-- Determine which wrapped segment was clicked
|
||||
local lineYOffset = (clickedLineNum - 1) * lineHeight
|
||||
local segmentNum = math.floor((relativeY - lineYOffset) / lineHeight) + 1
|
||||
segmentNum = math.max(1, math.min(segmentNum, #wrappedSegments))
|
||||
|
||||
local segment = wrappedSegments[segmentNum]
|
||||
|
||||
-- Find closest position within the segment
|
||||
local segmentText = segment.text
|
||||
local segmentLen = utf8.len(segmentText) or 0
|
||||
local closestPos = segment.startIdx
|
||||
local closestDist = math.huge
|
||||
|
||||
for i = 0, segmentLen do
|
||||
local offset = utf8.offset(segmentText, i + 1)
|
||||
local beforeText = offset and segmentText:sub(1, offset - 1) or segmentText
|
||||
local textWidth = font:getWidth(beforeText)
|
||||
local dist = math.abs(relativeX - textWidth)
|
||||
|
||||
if dist < closestDist then
|
||||
closestDist = dist
|
||||
closestPos = segment.startIdx + i
|
||||
end
|
||||
end
|
||||
|
||||
return charOffset + closestPos
|
||||
end
|
||||
|
||||
-- No wrapping - find closest position in the clicked line
|
||||
local closestPos = 0
|
||||
local closestDist = math.huge
|
||||
|
||||
for i = 0, lineLen do
|
||||
local offset = utf8.offset(clickedLine, i + 1)
|
||||
local beforeText = offset and clickedLine:sub(1, offset - 1) or clickedLine
|
||||
local textWidth = font:getWidth(beforeText)
|
||||
local dist = math.abs(relativeX - textWidth)
|
||||
|
||||
if dist < closestDist then
|
||||
closestDist = dist
|
||||
closestPos = i
|
||||
end
|
||||
end
|
||||
|
||||
return charOffset + closestPos
|
||||
end
|
||||
|
||||
--- Handle mouse click on text (set cursor position or start selection)
|
||||
---@param mouseX number -- Mouse X coordinate
|
||||
---@param mouseY number -- Mouse Y coordinate
|
||||
|
||||
@@ -690,12 +690,12 @@ function TestInputField:testMultilineTextSplitting()
|
||||
})
|
||||
|
||||
-- Trigger line splitting
|
||||
element:_splitLines()
|
||||
element._textEditor:_splitLines()
|
||||
|
||||
lu.assertEquals(#element._lines, 3)
|
||||
lu.assertEquals(element._lines[1], "Line 1")
|
||||
lu.assertEquals(element._lines[2], "Line 2")
|
||||
lu.assertEquals(element._lines[3], "Line 3")
|
||||
lu.assertEquals(#element._textEditor._lines, 3)
|
||||
lu.assertEquals(element._textEditor._lines[1], "Line 1")
|
||||
lu.assertEquals(element._textEditor._lines[2], "Line 2")
|
||||
lu.assertEquals(element._textEditor._lines[3], "Line 3")
|
||||
end
|
||||
|
||||
-- ====================
|
||||
@@ -1155,11 +1155,11 @@ function TestInputField:testMouseToTextPosition()
|
||||
element:focus()
|
||||
|
||||
-- Test conversion at start of element
|
||||
local pos = element:_mouseToTextPosition(10, 10)
|
||||
local pos = element._textEditor:mouseToTextPosition(10, 10)
|
||||
lu.assertEquals(pos, 0)
|
||||
|
||||
-- Test conversion far to the right (should be at end)
|
||||
pos = element:_mouseToTextPosition(200, 10)
|
||||
pos = element._textEditor:mouseToTextPosition(200, 10)
|
||||
lu.assertEquals(pos, 5) -- "Hello" has 5 characters
|
||||
end
|
||||
|
||||
@@ -1822,15 +1822,15 @@ function TestInputField:testMultilineMouseToTextPositionBasic()
|
||||
local lineHeight = font:getHeight()
|
||||
|
||||
-- Click at start (should be position 0)
|
||||
local pos = element:_mouseToTextPosition(10, 10)
|
||||
local pos = element._textEditor:mouseToTextPosition(10, 10)
|
||||
lu.assertEquals(pos, 0)
|
||||
|
||||
-- Click on second line start (should be after "Line 1\n" = position 7)
|
||||
pos = element:_mouseToTextPosition(10, 10 + lineHeight)
|
||||
pos = element._textEditor:mouseToTextPosition(10, 10 + lineHeight)
|
||||
lu.assertEquals(pos, 7)
|
||||
|
||||
-- Click on third line start (should be after "Line 1\nLine 2\n" = position 14)
|
||||
pos = element:_mouseToTextPosition(10, 10 + lineHeight * 2)
|
||||
pos = element._textEditor:mouseToTextPosition(10, 10 + lineHeight * 2)
|
||||
lu.assertEquals(pos, 14)
|
||||
end
|
||||
|
||||
@@ -1852,12 +1852,12 @@ function TestInputField:testMultilineMouseToTextPositionXCoordinate()
|
||||
local charWidth = font:getWidth("A")
|
||||
|
||||
-- Click in middle of first line (should be around position 1-2)
|
||||
local pos = element:_mouseToTextPosition(10 + charWidth * 1.5, 10)
|
||||
local pos = element._textEditor:mouseToTextPosition(10 + charWidth * 1.5, 10)
|
||||
lu.assertTrue(pos >= 1 and pos <= 2)
|
||||
|
||||
-- Click at end of second line (should be around position 6-7)
|
||||
-- Text is "ABC\nDEF\nGHI", so second line "DEF" ends at position 6 or 7 (newline)
|
||||
pos = element:_mouseToTextPosition(10 + charWidth * 3, 10 + lineHeight)
|
||||
pos = element._textEditor:mouseToTextPosition(10 + charWidth * 3, 10 + lineHeight)
|
||||
lu.assertTrue(pos >= 6 and pos <= 7)
|
||||
end
|
||||
|
||||
@@ -2076,11 +2076,11 @@ function TestInputField:testMultilineEmptyLinesHandling()
|
||||
local lineHeight = font:getHeight()
|
||||
|
||||
-- Click on empty line (second line)
|
||||
local pos = element:_mouseToTextPosition(10, 10 + lineHeight)
|
||||
local pos = element._textEditor:mouseToTextPosition(10, 10 + lineHeight)
|
||||
lu.assertEquals(pos, 7) -- After "Line 1\n"
|
||||
|
||||
-- Click on third line
|
||||
pos = element:_mouseToTextPosition(10, 10 + lineHeight * 2)
|
||||
pos = element._textEditor:mouseToTextPosition(10, 10 + lineHeight * 2)
|
||||
lu.assertEquals(pos, 8) -- After "Line 1\n\n"
|
||||
end
|
||||
|
||||
@@ -2101,7 +2101,7 @@ function TestInputField:testMultilineYCoordinateBeyondText()
|
||||
local lineHeight = font:getHeight()
|
||||
|
||||
-- Click way below the text (should clamp to last line)
|
||||
local pos = element:_mouseToTextPosition(10, 10 + lineHeight * 10)
|
||||
local pos = element._textEditor:mouseToTextPosition(10, 10 + lineHeight * 10)
|
||||
local textLen = utf8.len(element.text)
|
||||
|
||||
-- Should be at or near end of text
|
||||
|
||||
Reference in New Issue
Block a user