diff --git a/modules/game_textwindow/textwindow.lua b/modules/game_textwindow/textwindow.lua index dbb21df6..9c8d40c5 100644 --- a/modules/game_textwindow/textwindow.lua +++ b/modules/game_textwindow/textwindow.lua @@ -22,6 +22,8 @@ function destroy() end function getCursorPosByNewLine(str, count) + if count <= 1 then return 0 end + local i = 0 for n = 1, count-1 do local tPos = string.find(str, '\n', i) @@ -33,6 +35,32 @@ function getCursorPosByNewLine(str, count) return i - 1 end +function getLineByCursorPos(str, pos, maxLine) + for i = 1, maxLine do + if pos <= getCursorPosByNewLine(str, i) then + return i + end + end + + return maxLine + 1 +end + + +function getLineSizeByCursorPos(str, pos, maxLine) + for i = 1, maxLine + 1 do + if pos < getCursorPosByNewLine(str, i) then + return {minPos = getCursorPosByNewLine(str, i-1), maxPos = (getCursorPosByNewLine(str, i) - 1)} + end + end + + return {minPos = getCursorPosByNewLine(str, maxLine + 1), maxPos = str:len()} +end + +function string.count(str, pattern) + local _, _count = string.gsub(str, pattern, pattern) + return _count +end + function onGameEditText(id, itemId, maxLength, text, writter, time) if textWindow then return end textWindow = g_ui.createWidget('TextWindow', rootWidget) @@ -89,35 +117,76 @@ function onGameEditText(id, itemId, maxLength, text, writter, time) destroy() end - local _, newLineCount = string.gsub(text, '\n', '\n') + local newLineCount = string.count(textEdit:getText(), '\n') if(newLineCount >= 9) then textScroll:setMaximum(newLineCount-9) end - local _prev, _next, _current = 0, 11, 0 - local onValueChange = function() - local diff = textScroll:getValue() - _current + local _prev, _next = 0, 11 + local scrollOnValueChange = function(widget, value, delta) + local line = getLineByCursorPos(textEdit:getText(), textEdit:getCursorPos(), newLineCount) + if(delta > 0) then + textEdit:setCursorPos(getCursorPosByNewLine(textEdit:getText(), _next + delta - 1)) + if writeable then textEdit:setCursorPos(getCursorPosByNewLine(textEdit:getText(), line + delta)) end + else + textEdit:setCursorPos(getCursorPosByNewLine(textEdit:getText(), _prev + delta + 1)) + if writeable then textEdit:setCursorPos(getCursorPosByNewLine(textEdit:getText(), line + delta)) end + end - if(diff > 0) then - textEdit:setCursorPos(getCursorPosByNewLine(text, _next+(diff-1))) - else - textEdit:setCursorPos(getCursorPosByNewLine(text, _prev+(diff+1))) + _next = _next + delta + _prev = _prev + delta end - _current = textScroll:getValue() - _next = _next + diff - _prev = _prev + diff + textScroll.onValueChange = scrollOnValueChange + + local navigateVertical = function(up) -- Pressing Up / Down when scrollbar is at min / max value + local line = getLineByCursorPos(textEdit:getText(), textEdit:getCursorPos(), newLineCount) + if up and textScroll:getValue() == textScroll:getMinimum() then + textEdit:setCursorPos(getCursorPosByNewLine(textEdit:getText(), line - 1)) + elseif not up and textScroll:getValue() == textScroll:getMaximum() then + textEdit:setCursorPos(getCursorPosByNewLine(textEdit:getText(), line + 1)) + end end - textScroll.onValueChange = onValueChange - g_keyboard.bindKeyPress("Up", function() textScroll:setValue(textScroll:getValue()-1) end, textWindow, 400) - g_keyboard.bindKeyPress("Down", function() textScroll:setValue(textScroll:getValue()+1) end, textWindow, 400) + local navigateHorizontal = function(right) -- Pressing Left / Right to navigate in a line + local currentCursor = textEdit:getCursorPos() + local lineSize = getLineSizeByCursorPos(textEdit:getText(), currentCursor, newLineCount) + if right and currentCursor < lineSize.maxPos then + textEdit:setCursorPos(currentCursor+1) + elseif not right and currentCursor > lineSize.minPos then + textEdit:setCursorPos(currentCursor-1) + end + end + + local onKeyPress = function(widget, keyCode, keyModifiers) + if keyModifiers ~= 0 then + return false + end + + if keyCode == 16 or keyCode == 17 then -- Left / Right + navigateHorizontal((keyCode == 17)) + return true + elseif keyCode == 14 or keyCode == 15 then -- Up / Down + local up = (keyCode == 14) + navigateVertical(up) + + if up then + textScroll:setValue(textScroll:getValue() - 1) + else + textScroll:setValue(textScroll:getValue() + 1) + end + return true + end + return false + end if(not writeable) then textEdit:setCursorPos(0) + textWindow.onKeyPress = onKeyPress -- textEdit won't receive focus else textScroll:setValue(textScroll:getMaximum()) textEdit:setCursorPos(text:len()) + textEdit.onKeyPress = onKeyPress end okButton.onClick = doneFunc @@ -175,4 +244,4 @@ function onGameEditList(id, doorId, text) okButton.onClick = doneFunc textWindow.onEnter = doneFunc textWindow.onEscape = destroy -end +end \ No newline at end of file