mirror of
https://github.com/edubart/otclient.git
synced 2025-10-14 11:34:54 +02:00
Reimplement text edit scrolling in C++
* And update some corelib APIs
This commit is contained in:
@@ -10,7 +10,6 @@ FlatLabel < UILabel
|
||||
color: #aaaaaa
|
||||
size: 86 20
|
||||
text-offset: 3 3
|
||||
text-margin: 3
|
||||
image-source: /images/panel_flat.png
|
||||
image-border: 1
|
||||
|
||||
|
@@ -3,7 +3,7 @@ TextEdit < UITextEdit
|
||||
color: #aaaaaa
|
||||
size: 86 20
|
||||
text-offset: 0 3
|
||||
text-margin: 3
|
||||
padding: 3
|
||||
image-source: /images/textedit.png
|
||||
image-border: 1
|
||||
|
||||
|
@@ -301,7 +301,11 @@ KeyCodeDescs = {
|
||||
|
||||
NetworkMessageTypes = {
|
||||
Boolean = 1,
|
||||
Number = 2,
|
||||
String = 3,
|
||||
Table = 4
|
||||
U8 = 2,
|
||||
U16 = 3,
|
||||
U32 = 4,
|
||||
U64 = 5,
|
||||
NumberString = 6,
|
||||
String = 7,
|
||||
Table = 8
|
||||
}
|
||||
|
@@ -2,8 +2,16 @@ function InputMessage:getData()
|
||||
local dataType = self:getU8()
|
||||
if dataType == NetworkMessageTypes.Boolean then
|
||||
return numbertoboolean(self:getU8())
|
||||
elseif dataType == NetworkMessageTypes.Number then
|
||||
elseif dataType == NetworkMessageTypes.U8 then
|
||||
return self:getU8()
|
||||
elseif dataType == NetworkMessageTypes.U16 then
|
||||
return self:getU16()
|
||||
elseif dataType == NetworkMessageTypes.U32 then
|
||||
return self:getU32()
|
||||
elseif dataType == NetworkMessageTypes.U64 then
|
||||
return self:getU64()
|
||||
elseif dataType == NetworkMessageTypes.NumberString then
|
||||
return tonumber(self:getString())
|
||||
elseif dataType == NetworkMessageTypes.String then
|
||||
return self:getString()
|
||||
elseif dataType == NetworkMessageTypes.Table then
|
||||
@@ -16,11 +24,20 @@ end
|
||||
|
||||
function InputMessage:getTable()
|
||||
local ret = {}
|
||||
local size = self:getU32()
|
||||
local size = self:getU16()
|
||||
for i=1,size do
|
||||
local index = self:getData()
|
||||
local value = self:getData()
|
||||
ret[index] = value
|
||||
end
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
function InputMessage:getColor()
|
||||
local color = {}
|
||||
color.r = msg:getU8()
|
||||
color.g = msg:getU8()
|
||||
color.b = msg:getU8()
|
||||
color.a = msg:getU8()
|
||||
return color
|
||||
end
|
||||
|
@@ -24,3 +24,10 @@ function g_mouse.bindPressMove(widget, callback)
|
||||
return true
|
||||
end })
|
||||
end
|
||||
|
||||
function g_mouse.bindPress(widget, callback)
|
||||
connect(widget, { onMousePress = function(widget, mousePos, mouseButton)
|
||||
callback(mousePos, mouseButton)
|
||||
return true
|
||||
end })
|
||||
end
|
||||
|
@@ -3,8 +3,22 @@ function OutputMessage:addData(data)
|
||||
self:addU8(NetworkMessageTypes.Boolean)
|
||||
self:addU8(booleantonumber(data))
|
||||
elseif type(data) == 'number' then
|
||||
self:addU8(NetworkMessageTypes.Number)
|
||||
self:addU64(data)
|
||||
if math.isu8(data) then
|
||||
self:addU8(NetworkMessageTypes.U8)
|
||||
self:addU8(data)
|
||||
elseif math.isu16(data) then
|
||||
self:addU8(NetworkMessageTypes.U16)
|
||||
self:addU16(data)
|
||||
elseif math.isu32(data) then
|
||||
self:addU8(NetworkMessageTypes.U32)
|
||||
self:addU32(data)
|
||||
elseif math.isu64(data) then
|
||||
self:addU8(NetworkMessageTypes.U64)
|
||||
self:addU64(data)
|
||||
else -- negative or non integer numbers
|
||||
self:addU8(NetworkMessageTypes.NumberString)
|
||||
self:addString(tostring(data))
|
||||
end
|
||||
elseif type(data) == 'string' then
|
||||
self:addU8(NetworkMessageTypes.String)
|
||||
self:addString(data)
|
||||
@@ -19,9 +33,9 @@ end
|
||||
function OutputMessage:addTable(data)
|
||||
local size = 0
|
||||
|
||||
-- reserve for size
|
||||
-- reserve for size (should be addData, find a way to use it further)
|
||||
local sizePos = self:getWritePos()
|
||||
self:addU32(size)
|
||||
self:addU16(size)
|
||||
local sizeSize = self:getWritePos() - sizePos
|
||||
|
||||
-- add values
|
||||
@@ -34,9 +48,16 @@ function OutputMessage:addTable(data)
|
||||
-- write size
|
||||
local currentPos = self:getWritePos()
|
||||
self:setWritePos(sizePos)
|
||||
self:addU32(size)
|
||||
self:addU16(size)
|
||||
|
||||
-- fix msg size and go back to end
|
||||
self:setMessageSize(self:getMessageSize() - sizeSize)
|
||||
self:setWritePos(currentPos)
|
||||
end
|
||||
end
|
||||
|
||||
function OutputMessage:addColor(color)
|
||||
self:addU8(color.r)
|
||||
self:addU8(color.g)
|
||||
self:addU8(color.b)
|
||||
self:addU8(color.a)
|
||||
end
|
||||
|
@@ -93,6 +93,24 @@ function table.empty(t)
|
||||
return true
|
||||
end
|
||||
|
||||
function table.permute(t, n, count)
|
||||
n = n or #t
|
||||
for i=1,count or n do
|
||||
local j = math.random(i, n)
|
||||
t[i], t[j] = t[j], t[i]
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
function table.findbyfield(t, fieldname, fieldvalue)
|
||||
for _i,subt in pairs(t) do
|
||||
if subt[fieldname] == fieldvalue then
|
||||
return subt
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function table.toString(t)
|
||||
local maxn = #t
|
||||
local str = ""
|
||||
|
@@ -12,7 +12,7 @@ local function moveToolTip(first)
|
||||
local pos = g_window.getMousePosition()
|
||||
pos.y = pos.y + 1
|
||||
local xdif = g_window.getSize().width - (pos.x + toolTipLabel:getWidth())
|
||||
if xdif < 2 then
|
||||
if xdif < 10 then
|
||||
pos.x = pos.x - toolTipLabel:getWidth() - 3
|
||||
else
|
||||
pos.x = pos.x + 10
|
||||
|
@@ -3,6 +3,7 @@ UIComboBox = extends(UIWidget)
|
||||
|
||||
function UIComboBox.create()
|
||||
local combobox = UIComboBox.internalCreate()
|
||||
combobox:setFocusable(false)
|
||||
combobox.options = {}
|
||||
combobox.currentIndex = -1
|
||||
combobox.mouseScroll = true
|
||||
@@ -15,6 +16,15 @@ function UIComboBox:clearOptions()
|
||||
self:clearText()
|
||||
end
|
||||
|
||||
function UIComboBox:getOption(text)
|
||||
if not self.options then return nil end
|
||||
for i,v in ipairs(self.options) do
|
||||
if v.text == text then
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function UIComboBox:setCurrentOption(text)
|
||||
if not self.options then return end
|
||||
for i,v in ipairs(self.options) do
|
||||
@@ -27,6 +37,18 @@ function UIComboBox:setCurrentOption(text)
|
||||
end
|
||||
end
|
||||
|
||||
function UIComboBox:setCurrentOptionByData(data)
|
||||
if not self.options then return end
|
||||
for i,v in ipairs(self.options) do
|
||||
if v.data == data and self.currentIndex ~= i then
|
||||
self.currentIndex = i
|
||||
self:setText(v.text)
|
||||
self:onOptionChange(v.text, v.data)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function UIComboBox:setCurrentIndex(index)
|
||||
if index >= 1 and index <= #self.options then
|
||||
local v = self.options[index]
|
||||
|
114
modules/corelib/ui/uiinputbox.lua
Normal file
114
modules/corelib/ui/uiinputbox.lua
Normal file
@@ -0,0 +1,114 @@
|
||||
if not UIWindow then dofile 'uiwindow' end
|
||||
|
||||
-- @docclass
|
||||
UIInputBox = extends(UIWindow)
|
||||
|
||||
function UIInputBox.create(title, okCallback, cancelCallback)
|
||||
local inputBox = UIInputBox.internalCreate()
|
||||
|
||||
inputBox:setText(title)
|
||||
inputBox.inputs = {}
|
||||
inputBox.onEnter = function()
|
||||
local results = {}
|
||||
for _,func in pairs(inputBox.inputs) do
|
||||
table.insert(results, func())
|
||||
end
|
||||
okCallback(unpack(results))
|
||||
inputBox:destroy()
|
||||
end
|
||||
inputBox.onEscape = function()
|
||||
if cancelCallback then
|
||||
cancelCallback()
|
||||
end
|
||||
inputBox:destroy()
|
||||
end
|
||||
|
||||
return inputBox
|
||||
end
|
||||
|
||||
function UIInputBox:addLabel(text)
|
||||
local label = g_ui.createWidget('InputBoxLabel', self)
|
||||
label:setText(text)
|
||||
return label
|
||||
end
|
||||
|
||||
function UIInputBox:addLineEdit(labelText, defaultText, maxLength)
|
||||
if labelText then self:addLabel(labelText) end
|
||||
local lineEdit = g_ui.createWidget('InputBoxLineEdit', self)
|
||||
if defaultText then lineEdit:setText(defaultText) end
|
||||
if maxLength then lineEdit:setMaxLength(maxLength) end
|
||||
table.insert(self.inputs, function() return lineEdit:getText() end)
|
||||
return lineEdit
|
||||
end
|
||||
|
||||
function UIInputBox:addTextEdit(labelText, defaultText, maxLength, visibleLines)
|
||||
if labelText then self:addLabel(labelText) end
|
||||
local textEdit = g_ui.createWidget('InputBoxTextEdit', self)
|
||||
if defaultText then textEdit:setText(defaultText) end
|
||||
if maxLength then textEdit:setMaxLength(maxLength) end
|
||||
visibleLines = visibleLines or 1
|
||||
textEdit:setHeight(textEdit:getHeight() * visibleLines)
|
||||
table.insert(self.inputs, function() return textEdit:getText() end)
|
||||
return textEdit
|
||||
end
|
||||
|
||||
function UIInputBox:addCheckBox(text, checked)
|
||||
local checkBox = g_ui.createWidget('InputBoxCheckBox', self)
|
||||
checkBox:setText(text)
|
||||
checkBox:setChecked(checked)
|
||||
table.insert(self.inputs, function() return checkBox:isChecked() end)
|
||||
return checkBox
|
||||
end
|
||||
|
||||
function UIInputBox:addComboBox(labelText, ...)
|
||||
if labelText then self:addLabel(labelText) end
|
||||
local comboBox = g_ui.createWidget('InputBoxComboBox', self)
|
||||
local options = {...}
|
||||
for i=1,#options do
|
||||
comboBox:addOption(options[i])
|
||||
end
|
||||
table.insert(self.inputs, function() return comboBox:getCurrentOption() end)
|
||||
return comboBox
|
||||
end
|
||||
|
||||
function UIInputBox:addSpinBox(labelText, minimum, maximum, value, step)
|
||||
if labelText then self:addLabel(labelText) end
|
||||
local spinBox = g_ui.createWidget('InputBoxSpinBox', self)
|
||||
spinBox:setMinimum(minimum)
|
||||
spinBox:setMaximum(maximum)
|
||||
spinBox:setValue(value)
|
||||
spinBox:setStep(step)
|
||||
table.insert(self.inputs, function() return spinBox:getValue() end)
|
||||
return spinBox
|
||||
end
|
||||
|
||||
function UIInputBox:display(okButtonText, cancelButtonText)
|
||||
okButtonText = okButtonText or tr('Ok')
|
||||
cancelButtonText = cancelButtonText or tr('Cancel')
|
||||
|
||||
local buttonsWidget = g_ui.createWidget('InputBoxButtonsPanel', self)
|
||||
local okButton = g_ui.createWidget('InputBoxButton', buttonsWidget)
|
||||
okButton:setText(okButtonText)
|
||||
okButton.onClick = self.onEnter
|
||||
|
||||
local cancelButton = g_ui.createWidget('InputBoxButton', buttonsWidget)
|
||||
cancelButton:setText(cancelButtonText)
|
||||
cancelButton.onClick = self.onEscape
|
||||
|
||||
buttonsWidget:setHeight(okButton:getHeight())
|
||||
|
||||
rootWidget:addChild(self)
|
||||
self:setStyle('InputBoxWindow')
|
||||
end
|
||||
|
||||
function displayTextInputBox(title, label, okCallback, cancelCallback)
|
||||
local inputBox = UIInputBox.create(title, okCallback, cancelCallback)
|
||||
inputBox:addLineEdit(label)
|
||||
inputBox:display()
|
||||
end
|
||||
|
||||
function displayNumberInputBox(title, label, okCallback, cancelCallback, min, max, value, step)
|
||||
local inputBox = UIInputBox.create(title, okCallback, cancelCallback)
|
||||
inputBox:addSpinBox(label, min, max, value, step)
|
||||
inputBox:display()
|
||||
end
|
@@ -22,10 +22,14 @@ function UIPopupMenu:display(pos)
|
||||
currentMenu:destroy()
|
||||
end
|
||||
|
||||
if pos == nil then
|
||||
pos = g_window.getMousePosition()
|
||||
end
|
||||
|
||||
rootWidget:addChild(self)
|
||||
self:setPosition(pos)
|
||||
self:grabMouse()
|
||||
self:grabKeyboard()
|
||||
--self:grabKeyboard()
|
||||
currentMenu = self
|
||||
end
|
||||
|
||||
|
@@ -6,6 +6,10 @@ function UIProgressBar.create()
|
||||
progressbar:setFocusable(false)
|
||||
progressbar:setPhantom(true)
|
||||
progressbar.percent = 0
|
||||
progressbar.bgBorderLeft = 0
|
||||
progressbar.bgBorderRight = 0
|
||||
progressbar.bgBorderTop = 0
|
||||
progressbar.bgBorderBottom = 0
|
||||
progressbar:updateBackground()
|
||||
return progressbar
|
||||
end
|
||||
@@ -25,11 +29,30 @@ function UIProgressBar:getPercentPixels()
|
||||
end
|
||||
|
||||
function UIProgressBar:updateBackground()
|
||||
local width = math.round(math.max((self.percent * self:getWidth())/100, 1))
|
||||
local height = self:getHeight()
|
||||
self:setBackgroundSize({width=width, height=height})
|
||||
local width = math.round(math.max((self.percent * (self:getWidth() - self.bgBorderLeft - self.bgBorderRight))/100, 1))
|
||||
local height = self:getHeight() - self.bgBorderTop - self.bgBorderBottom
|
||||
local rect = { x = self.bgBorderLeft, y = self.bgBorderTop, width = width, height = height }
|
||||
self:setBackgroundRect(rect)
|
||||
end
|
||||
|
||||
function UIProgressBar:onStyleApply(name, node)
|
||||
for name,value in pairs(node) do
|
||||
if name == 'background-border-left' then
|
||||
self.bgBorderLeft = tonumber(value)
|
||||
elseif name == 'background-border-right' then
|
||||
self.bgBorderRight = tonumber(value)
|
||||
elseif name == 'background-border-top' then
|
||||
self.bgBorderTop = tonumber(value)
|
||||
elseif name == 'background-border-bottom' then
|
||||
self.bgBorderBottom = tonumber(value)
|
||||
elseif name == 'background-border' then
|
||||
self.bgBorderLeft = tonumber(value)
|
||||
self.bgBorderRight = tonumber(value)
|
||||
self.bgBorderTop = tonumber(value)
|
||||
self.bgBorderBottom = tonumber(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function UIProgressBar:onGeometryChange(oldRect, newRect)
|
||||
self:updateBackground()
|
||||
|
@@ -3,11 +3,14 @@ UISpinBox = extends(UITextEdit)
|
||||
|
||||
function UISpinBox.create()
|
||||
local spinbox = UISpinBox.internalCreate()
|
||||
spinbox:setFocusable(false)
|
||||
spinbox:setValidCharacters('0123456789')
|
||||
spinbox.displayButtons = true
|
||||
spinbox.minimum = 0
|
||||
spinbox.maximum = 0
|
||||
spinbox.value = 0
|
||||
spinbox.step = 1
|
||||
spinbox.firstchange = true
|
||||
spinbox:setText("0")
|
||||
return spinbox
|
||||
end
|
||||
@@ -21,6 +24,14 @@ function UISpinBox:onMouseWheel(mousePos, direction)
|
||||
return true
|
||||
end
|
||||
|
||||
function UISpinBox:onKeyPress()
|
||||
if self.firstchange then
|
||||
self.firstchange = false
|
||||
self:setText('')
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function UISpinBox:onTextChange(text, oldText)
|
||||
if text:len() == 0 then
|
||||
self:setValue(self.minimum)
|
||||
@@ -79,14 +90,15 @@ function UISpinBox:hideButtons()
|
||||
end
|
||||
|
||||
function UISpinBox:up()
|
||||
self:setValue(self.value + 1)
|
||||
self:setValue(self.value + self.step)
|
||||
end
|
||||
|
||||
function UISpinBox:down()
|
||||
self:setValue(self.value - 1)
|
||||
self:setValue(self.value - self.step)
|
||||
end
|
||||
|
||||
function UISpinBox:setValue(value)
|
||||
value = value or 0
|
||||
value = math.max(math.min(self.maximum, value), self.minimum)
|
||||
if value == self.value then return end
|
||||
if self:getText():len() > 0 then
|
||||
@@ -107,6 +119,7 @@ function UISpinBox:setValue(value)
|
||||
end
|
||||
|
||||
function UISpinBox:setMinimum(minimum)
|
||||
minimum = minimum or -9223372036854775808
|
||||
self.minimum = minimum
|
||||
if self.minimum > self.maximum then
|
||||
self.maximum = self.minimum
|
||||
@@ -117,12 +130,17 @@ function UISpinBox:setMinimum(minimum)
|
||||
end
|
||||
|
||||
function UISpinBox:setMaximum(maximum)
|
||||
maximum = maximum or 9223372036854775807
|
||||
self.maximum = maximum
|
||||
if self.value > maximum then
|
||||
self:setValue(maximum)
|
||||
end
|
||||
end
|
||||
|
||||
function UISpinBox:setStep(step)
|
||||
self.step = step or 1
|
||||
end
|
||||
|
||||
function UISpinBox:getValue()
|
||||
return self.value
|
||||
end
|
||||
|
@@ -193,6 +193,9 @@ function UITabBar:selectTab(tab)
|
||||
tab:setChecked(true)
|
||||
tab:setOn(false)
|
||||
tab.blinking = false
|
||||
|
||||
local parent = tab:getParent()
|
||||
parent:focusChild(tab, MouseFocusReason)
|
||||
end
|
||||
|
||||
function UITabBar:selectNextTab()
|
||||
|
77
modules/corelib/ui/uitextedit.lua
Normal file
77
modules/corelib/ui/uitextedit.lua
Normal file
@@ -0,0 +1,77 @@
|
||||
function UITextEdit:onStyleApply(styleName, styleNode)
|
||||
for name,value in pairs(styleNode) do
|
||||
if name == 'vertical-scrollbar' then
|
||||
addEvent(function()
|
||||
self:setVerticalScrollBar(self:getParent():getChildById(value))
|
||||
end)
|
||||
elseif name == 'horizontal-scrollbar' then
|
||||
addEvent(function()
|
||||
self:setHorizontalScrollBar(self:getParent():getChildById(value))
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function UITextEdit:onMouseWheel(mousePos, mouseWheel)
|
||||
if self.verticalScrollBar and self:isMultiline() then
|
||||
if mouseWheel == MouseWheelUp then
|
||||
self.verticalScrollBar:decrement()
|
||||
else
|
||||
self.verticalScrollBar:increment()
|
||||
end
|
||||
elseif self.horizontalScrollBar then
|
||||
if mouseWheel == MouseWheelUp then
|
||||
self.horizontalScrollBar:increment()
|
||||
else
|
||||
self.horizontalScrollBar:decrement()
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function UITextEdit:onTextAreaUpdate(virtualOffset, virtualSize, totalSize)
|
||||
self:updateScrollBars()
|
||||
end
|
||||
|
||||
function UITextEdit:setVerticalScrollBar(scrollbar)
|
||||
self.verticalScrollBar = scrollbar
|
||||
self.verticalScrollBar.onValueChange = function(scrollbar, value)
|
||||
local virtualOffset = self:getTextVirtualOffset()
|
||||
virtualOffset.y = value
|
||||
self:setTextVirtualOffset(virtualOffset)
|
||||
end
|
||||
self:updateScrollBars()
|
||||
end
|
||||
|
||||
function UITextEdit:setHorizontalScrollBar(scrollbar)
|
||||
self.horizontalScrollBar = scrollbar
|
||||
self.horizontalScrollBar.onValueChange = function(scrollbar, value)
|
||||
local virtualOffset = self:getTextVirtualOffset()
|
||||
virtualOffset.x = value
|
||||
self:setTextVirtualOffset(virtualOffset)
|
||||
end
|
||||
self:updateScrollBars()
|
||||
end
|
||||
|
||||
function UITextEdit:updateScrollBars()
|
||||
local scrollSize = self:getTextTotalSize()
|
||||
local scrollWidth = math.max(scrollSize.width - self:getTextVirtualSize().width, 0)
|
||||
local scrollHeight = math.max(scrollSize.height - self:getTextVirtualSize().height, 0)
|
||||
|
||||
local scrollbar = self.verticalScrollBar
|
||||
if scrollbar then
|
||||
scrollbar:setMinimum(0)
|
||||
scrollbar:setMaximum(scrollHeight)
|
||||
scrollbar:setValue(self:getTextVirtualOffset().y)
|
||||
end
|
||||
|
||||
local scrollbar = self.horizontalScrollBar
|
||||
if scrollbar then
|
||||
scrollbar:setMinimum(0)
|
||||
scrollbar:setMaximum(scrollWidth)
|
||||
scrollbar:setValue(self:getTextVirtualOffset().x)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- todo: ontext change, focus to cursor
|
@@ -228,10 +228,16 @@ function resolvepath(filePath, depth)
|
||||
end
|
||||
end
|
||||
|
||||
function toboolean(str)
|
||||
str = str:trim():lower()
|
||||
if str == '1' or str == 'true' then
|
||||
return true
|
||||
function toboolean(v)
|
||||
if type(v) == 'string' then
|
||||
v = v:trim():lower()
|
||||
if v == '1' or v == 'true' then
|
||||
return true
|
||||
end
|
||||
elseif type(v) == 'number' then
|
||||
if v == 1 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
@@ -23,46 +23,6 @@ function destroy()
|
||||
end
|
||||
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)
|
||||
if tPos then
|
||||
i = tPos+1
|
||||
end
|
||||
end
|
||||
|
||||
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)
|
||||
@@ -118,82 +78,14 @@ function onGameEditText(id, itemId, maxLength, text, writter, time)
|
||||
end
|
||||
destroy()
|
||||
end
|
||||
|
||||
local newLineCount = string.count(textEdit:getText(), '\n')
|
||||
if newLineCount >= 9 then
|
||||
textScroll:setMaximum(newLineCount-9)
|
||||
end
|
||||
|
||||
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) - 1)
|
||||
if writeable then textEdit:setCursorPos(getCursorPosByNewLine(textEdit:getText(), line + delta)) end
|
||||
end
|
||||
|
||||
_next = _next + delta
|
||||
_prev = _prev + delta
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
cancelButton.onClick = destroy
|
||||
--textWindow.onEnter = doneFunc -- this should be '\n'
|
||||
|
||||
if not writeable then
|
||||
textWindow.onEnter = doneFunc
|
||||
end
|
||||
|
||||
textWindow.onEscape = destroy
|
||||
end
|
||||
|
||||
@@ -222,28 +114,3 @@ function onGameEditList(id, doorId, text)
|
||||
textWindow.onEscape = destroy
|
||||
end
|
||||
|
||||
|
||||
function onGameEditList(id, doorId, text)
|
||||
if textWindow then return end
|
||||
textWindow = g_ui.createWidget('TextWindow', rootWidget)
|
||||
|
||||
local textEdit = textWindow:getChildById('text')
|
||||
local description = textWindow:getChildById('description')
|
||||
local okButton = textWindow:getChildById('okButton')
|
||||
local cancelButton = textWindow:getChildById('cancelButton')
|
||||
|
||||
textEdit:setMaxLength(8192)
|
||||
textEdit:setText(text)
|
||||
textEdit:setEnabled(true)
|
||||
description:setText(tr('Enter one name per line.'))
|
||||
textWindow:setText(tr('Edit List'))
|
||||
|
||||
doneFunc = function()
|
||||
g_game.editList(id, doorId, textEdit:getText())
|
||||
destroy()
|
||||
end
|
||||
|
||||
okButton.onClick = doneFunc
|
||||
textWindow.onEnter = doneFunc
|
||||
textWindow.onEscape = destroy
|
||||
end
|
||||
|
@@ -1,12 +1,10 @@
|
||||
TextWindow < MainWindow
|
||||
id: textWindow
|
||||
size: 280 280
|
||||
@onEscape: self:destroy()
|
||||
size: 300 280
|
||||
|
||||
UIItem
|
||||
Item
|
||||
id: textItem
|
||||
virtual: true
|
||||
size: 32 32
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
||||
@@ -15,43 +13,40 @@ TextWindow < MainWindow
|
||||
anchors.top: parent.top
|
||||
anchors.left: textItem.right
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: text.top
|
||||
text-align: left
|
||||
margin-left: 8
|
||||
margin-bottom: 10
|
||||
text-auto-resize: true
|
||||
text-align: left
|
||||
text-wrap: true
|
||||
|
||||
MultilineTextEdit
|
||||
id: text
|
||||
anchors.fill: parent
|
||||
anchors.top: textItem.bottom
|
||||
margin-right: 10
|
||||
margin-top: 30
|
||||
margin-bottom: 30
|
||||
anchors.top: textScroll.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: textScroll.left
|
||||
anchors.bottom: textScroll.bottom
|
||||
vertical-scrollbar: textScroll
|
||||
|
||||
VerticalScrollBar
|
||||
id: textScroll
|
||||
anchors.left: prev.right
|
||||
anchors.top: prev.top
|
||||
anchors.bottom: prev.bottom
|
||||
minimum: 0
|
||||
maximum: 0
|
||||
step: 1
|
||||
value: 0
|
||||
anchors.top: description.bottom
|
||||
anchors.bottom: okButton.top
|
||||
anchors.right: parent.right
|
||||
margin-top: 10
|
||||
margin-bottom: 10
|
||||
step: 16
|
||||
pixels-scroll: true
|
||||
|
||||
Button
|
||||
id: cancelButton
|
||||
!text: tr('Cancel')
|
||||
anchors.top: next.top
|
||||
anchors.right: next.left
|
||||
margin-right: 8
|
||||
width: 60
|
||||
@onClick: self:getParent():destroy()
|
||||
|
||||
Button
|
||||
id: okButton
|
||||
!text: tr('Ok')
|
||||
anchors.top: text.bottom
|
||||
anchors.right: text.right
|
||||
margin-top: 10
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: next.left
|
||||
margin-right: 10
|
||||
width: 60
|
||||
|
||||
Button
|
||||
id: cancelButton
|
||||
!text: tr('Cancel')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: 60
|
||||
|
Reference in New Issue
Block a user