Skip to content

Commit 4c50e57

Browse files
committed
Added getInfoAtCursor() and getInfoAtCharacter().
1 parent 0d64719 commit 4c50e57

2 files changed

Lines changed: 116 additions & 19 deletions

File tree

InputField.lua

Lines changed: 100 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
getBlinkPhase, resetBlinking
4444
getCursor, setCursor, moveCursor, getCursorSelectionSide, getAnchorSelectionSide
4545
getCursorLayout
46-
getInfoAtCoords
46+
getInfoAtCoords, getInfoAtCursor, getInfoAtCharacter
4747
getScroll, getScrollX, getScrollY, setScroll, setScrollX, setScrollY, scroll, scrollToCursor
4848
getScrollHandles, getScrollHandleHorizontal, getScrollHandleVertical
4949
getScrollLimits
@@ -1445,10 +1445,10 @@ end
14451445
--
14461446
-- Info table fields:
14471447
-- cursorPosition -- integer Cursor position.
1448-
-- lineIndex -- integer Visible line index.
1449-
-- linePosition -- integer Visible line start position.
14501448
-- characterPosition -- integer Character position. (Is set even if hasText is false.)
14511449
-- hasText -- boolean Whether there's text directly at the coordinates.
1450+
-- lineIndex -- integer Visible line index.
1451+
-- linePosition -- integer Visible line start position.
14521452
--
14531453
-- Note: The coordinates must be relative to the field's position on the screen.
14541454
--
@@ -1459,10 +1459,10 @@ function InputField.getInfoAtCoords(field, x, y, info)
14591459

14601460
if field.text == "" then
14611461
info.cursorPosition = 0
1462-
info.lineIndex = 1
1463-
info.linePosition = 1
14641462
info.characterPosition = 1
14651463
info.hasText = false
1464+
info.lineIndex = 1
1465+
info.linePosition = 1
14661466

14671467
else
14681468
local curPos, visualLineI, visualLineIUnclamped = getCursorPositionAtCoordinates(field, x+field.scrollX, y+field.scrollY)
@@ -1483,15 +1483,108 @@ function InputField.getInfoAtCoords(field, x, y, info)
14831483
local xInText = unalignOnLine(field, line, x+field.scrollX)
14841484

14851485
info.cursorPosition = curPos
1486-
info.lineIndex = lineI
1487-
info.linePosition = linePos1
14881486
info.characterPosition = math.min(linePos1+charPosOnLine-1, utf8.len(field.text))
14891487
info.hasText = field.wrappedText[visualLineIUnclamped] ~= nil and xInText >= 0 and xInText < field.font:getWidth(line)
1488+
info.lineIndex = lineI
1489+
info.linePosition = linePos1
14901490
end
14911491

14921492
return info
14931493
end
14941494

1495+
--
1496+
-- info = field:getInfoAtCursor( cursorPosition [, info={} ] )
1497+
--
1498+
-- Info table fields:
1499+
-- x -- integer X position.
1500+
-- y -- integer Y/top position.
1501+
-- height -- integer Line height.
1502+
-- lineIndex -- integer Visible line index.
1503+
-- linePosition -- integer Visible line start position.
1504+
--
1505+
function InputField.getInfoAtCursor(field, pos, info)
1506+
updateWrap(field)
1507+
1508+
info = info or {}
1509+
1510+
if field.text == "" then
1511+
info.x = alignOnLine(field, "", 0)
1512+
info.y = 0
1513+
info.height = field.font:getHeight()
1514+
info.lineIndex = 1
1515+
info.linePosition = 1
1516+
1517+
else
1518+
pos = clamp(pos, 0, utf8.len(field.text))
1519+
1520+
local line, curPosOnLine, lineI, linePos1, linePos2 = getLineInfoAtPosition(field, pos)
1521+
1522+
local savedCursorPosition = field.cursorPosition
1523+
field.cursorPosition = pos
1524+
local x, y, h = field:getCursorLayout()
1525+
field.cursorPosition = savedCursorPosition
1526+
1527+
info.x = x
1528+
info.y = y
1529+
info.height = h
1530+
info.lineIndex = lineI
1531+
info.linePosition = linePos1
1532+
end
1533+
1534+
return info
1535+
end
1536+
1537+
--
1538+
-- info = field:getInfoAtCharacter( characterPosition [, info={} ] )
1539+
--
1540+
-- Info table fields:
1541+
-- character -- string The character (unobfuscated if field type is "password").
1542+
-- x -- integer Character x/left position.
1543+
-- y -- integer Character y/top position.
1544+
-- width -- integer Character width.
1545+
-- height -- integer Character/line height.
1546+
-- lineIndex -- integer Visible line index.
1547+
-- linePosition -- integer Visible line start position.
1548+
--
1549+
-- Returns nil if characterPosition is invalid or points at a newline.
1550+
--
1551+
function InputField.getInfoAtCharacter(field, pos, info)
1552+
updateWrap(field)
1553+
1554+
local text = field.text
1555+
1556+
if
1557+
text == "" or pos < 1 or pos > utf8.len(text) -- Error: Out-of-range!
1558+
or utf8.codepoint(text, utf8.offset(text, pos)) == 10 -- Don't return info about newlines.
1559+
then
1560+
return nil
1561+
end
1562+
1563+
local line, curPosOnLine, lineI, linePos1, linePos2 = getLineInfoAtPosition(field, pos-1)
1564+
1565+
local i1 = utf8.offset(line, curPosOnLine+1)
1566+
local i2 = utf8GetEndOffset(line, curPosOnLine+1)
1567+
local visibleChar = line:sub(i1, i2)
1568+
1569+
local preText = line:sub(1, i1-1) -- @Speed @Memory
1570+
local x = alignOnLine(field, line, field.font:getWidth(preText))
1571+
1572+
local fontH = field.font:getHeight()
1573+
local lineDist = math.ceil(fontH*field.font:getLineHeight())
1574+
local y = (lineI-1) * lineDist
1575+
1576+
info = info or {}
1577+
info.character = (field.type == "password") and text:sub(utf8.offset(text, pos), utf8GetEndOffset(text, pos)) or visibleChar
1578+
info.x = x
1579+
info.y = y
1580+
info.width = field.font:getWidth(visibleChar)
1581+
info.height = fontH
1582+
info.lineIndex = lineI
1583+
info.linePosition = linePos1
1584+
1585+
return info
1586+
end
1587+
14951588

14961589

14971590
----------------------------------------------------------------

examples/multipleFields/main.lua

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -355,28 +355,32 @@ function love.draw()
355355
local hoveredTextInput, textInputNumber = getTextInputAtCoords(love.mouse.getPosition())
356356

357357
if hoveredTextInput then
358-
local field = hoveredTextInput.field
359-
local fieldX = hoveredTextInput.x + FIELD_PADDING
360-
local fieldY = hoveredTextInput.y + FIELD_PADDING
361-
local mx, my = love.mouse.getPosition()
362-
local info = field:getInfoAtCoords(mx-fieldX, my-fieldY)
363-
local line = field:getVisibleLine(info.lineIndex)
358+
local field = hoveredTextInput.field
359+
local fieldX = hoveredTextInput.x + FIELD_PADDING
360+
local fieldY = hoveredTextInput.y + FIELD_PADDING
361+
local mx, my = love.mouse.getPosition()
362+
local info = field:getInfoAtCoords(mx-fieldX, my-fieldY)
363+
local charText = "none"
364+
365+
if info.hasText then
366+
local charInfo = field:getInfoAtCharacter(info.characterPosition)
367+
charText = string.format("position=%d, character='%s'", info.characterPosition, charInfo.character)
368+
end
364369

365370
local text = string.format(
366-
"Field #%d, type=%s, alignment=%s\n"
371+
"Field #%d, type=%s, alignment=%s, busy=%s\n"
367372
.. "Cursor: position=%d\n"
368373
.. "Selection: position=%d, length=%d\n"
369374
.. "At mouse:\n"
370-
.. " Character: position=%s\n"
371375
.. " Cursor: position=%d\n"
376+
.. " Character: %s\n"
372377
.. " Line: index=%d, position=%d, length=%d",
373-
textInputNumber, field:getType(), field:getAlignment(),
378+
textInputNumber, field:getType(), field:getAlignment(), (field:isBusy() and "yes" or "no"),
374379
field:getCursor(),
375380
field:getSelection(), select(2, field:getSelection())-field:getSelection(),
376-
(info.hasText and tostring(info.characterPosition) or "none"),
377381
info.cursorPosition,
378-
info.lineIndex,
379-
info.linePosition, require"utf8".len(line)
382+
charText,
383+
info.lineIndex, info.linePosition, require"utf8".len(field:getVisibleLine(info.lineIndex))
380384
)
381385
LG.print(text, 3, LG.getHeight()-3-10*extraFont:getHeight())
382386
end

0 commit comments

Comments
 (0)