mirror of
https://github.com/linux-man/LoveFrames.git
synced 2024-11-18 16:04:22 +00:00
Merge pull request #148 from Stepets/master
Textinput scrolls on indicator position change
This commit is contained in:
commit
ca0655b135
2
init.lua
2
init.lua
@ -8,6 +8,7 @@ require(path .. ".libraries.util")
|
||||
require(path .. ".libraries.skins")
|
||||
require(path .. ".libraries.templates")
|
||||
require(path .. ".libraries.debug")
|
||||
require(path .. ".libraries.utf8")
|
||||
local loveframes = require(path .. ".libraries.common")
|
||||
|
||||
-- library info
|
||||
@ -52,6 +53,7 @@ require(dir .. ".libraries.util")
|
||||
require(dir .. ".libraries.skins")
|
||||
require(dir .. ".libraries.templates")
|
||||
require(dir .. ".libraries.debug")
|
||||
require(dir .. ".libraries.utf8")
|
||||
|
||||
-- replace all "." with "/" in the directory setting
|
||||
dir = dir:gsub("\\", "/"):gsub("(%a)%.(%a)", "%1/%2")
|
||||
|
398
libraries/utf8.lua
Normal file
398
libraries/utf8.lua
Normal file
@ -0,0 +1,398 @@
|
||||
-- $Id: utf8.lua 179 2009-04-03 18:10:03Z pasta $
|
||||
--
|
||||
-- Provides UTF-8 aware string functions implemented in pure lua:
|
||||
-- * string.utf8len(s)
|
||||
-- * string.utf8sub(s, i, j)
|
||||
-- * string.utf8reverse(s)
|
||||
-- * string.utf8char(unicode)
|
||||
-- * string.utf8unicode(s, i, j)
|
||||
-- * string.utf8gensub(s, sub_len)
|
||||
--
|
||||
-- If utf8data.lua (containing the lower<->upper case mappings) is loaded, these
|
||||
-- additional functions are available:
|
||||
-- * string.utf8upper(s)
|
||||
-- * string.utf8lower(s)
|
||||
--
|
||||
-- All functions behave as their non UTF-8 aware counterparts with the exception
|
||||
-- that UTF-8 characters are used instead of bytes for all units.
|
||||
|
||||
--[[
|
||||
Copyright (c) 2006-2007, Kyle Smith
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
--]]
|
||||
|
||||
-- ABNF from RFC 3629
|
||||
--
|
||||
-- UTF8-octets = *( UTF8-char )
|
||||
-- UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
|
||||
-- UTF8-1 = %x00-7F
|
||||
-- UTF8-2 = %xC2-DF UTF8-tail
|
||||
-- UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
|
||||
-- %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
|
||||
-- UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
|
||||
-- %xF4 %x80-8F 2( UTF8-tail )
|
||||
-- UTF8-tail = %x80-BF
|
||||
--
|
||||
|
||||
local len = string.len
|
||||
local sub = string.sub
|
||||
local char = string.char
|
||||
|
||||
-- returns the number of bytes used by the UTF-8 character at byte i in s
|
||||
-- also doubles as a UTF-8 character validator
|
||||
local function utf8charbytes (s, i)
|
||||
-- argument defaults
|
||||
i = i or 1
|
||||
|
||||
-- argument checking
|
||||
if type(s) ~= "string" then
|
||||
error("bad argument #1 to 'utf8charbytes' (string expected, got ".. type(s).. ")")
|
||||
end
|
||||
if type(i) ~= "number" then
|
||||
error("bad argument #2 to 'utf8charbytes' (number expected, got ".. type(i).. ")")
|
||||
end
|
||||
|
||||
local c = s:byte(i)
|
||||
|
||||
-- determine bytes needed for character, based on RFC 3629
|
||||
-- validate byte 1
|
||||
if c > 0 and c <= 127 then
|
||||
-- UTF8-1
|
||||
return 1
|
||||
|
||||
elseif c >= 194 and c <= 223 then
|
||||
-- UTF8-2
|
||||
local c2 = s:byte(i + 1)
|
||||
|
||||
if not c2 then
|
||||
error("UTF-8 string terminated early")
|
||||
end
|
||||
|
||||
-- validate byte 2
|
||||
if c2 < 128 or c2 > 191 then
|
||||
error("Invalid UTF-8 character")
|
||||
end
|
||||
|
||||
return 2
|
||||
|
||||
elseif c >= 224 and c <= 239 then
|
||||
-- UTF8-3
|
||||
local c2 = s:byte(i + 1)
|
||||
local c3 = s:byte(i + 2)
|
||||
|
||||
if not c2 or not c3 then
|
||||
error("UTF-8 string terminated early")
|
||||
end
|
||||
|
||||
-- validate byte 2
|
||||
if c == 224 and (c2 < 160 or c2 > 191) then
|
||||
error("Invalid UTF-8 character")
|
||||
elseif c == 237 and (c2 < 128 or c2 > 159) then
|
||||
error("Invalid UTF-8 character")
|
||||
elseif c2 < 128 or c2 > 191 then
|
||||
error("Invalid UTF-8 character")
|
||||
end
|
||||
|
||||
-- validate byte 3
|
||||
if c3 < 128 or c3 > 191 then
|
||||
error("Invalid UTF-8 character")
|
||||
end
|
||||
|
||||
return 3
|
||||
|
||||
elseif c >= 240 and c <= 244 then
|
||||
-- UTF8-4
|
||||
local c2 = s:byte(i + 1)
|
||||
local c3 = s:byte(i + 2)
|
||||
local c4 = s:byte(i + 3)
|
||||
|
||||
if not c2 or not c3 or not c4 then
|
||||
error("UTF-8 string terminated early")
|
||||
end
|
||||
|
||||
-- validate byte 2
|
||||
if c == 240 and (c2 < 144 or c2 > 191) then
|
||||
error("Invalid UTF-8 character")
|
||||
elseif c == 244 and (c2 < 128 or c2 > 143) then
|
||||
error("Invalid UTF-8 character")
|
||||
elseif c2 < 128 or c2 > 191 then
|
||||
error("Invalid UTF-8 character")
|
||||
end
|
||||
|
||||
-- validate byte 3
|
||||
if c3 < 128 or c3 > 191 then
|
||||
error("Invalid UTF-8 character")
|
||||
end
|
||||
|
||||
-- validate byte 4
|
||||
if c4 < 128 or c4 > 191 then
|
||||
error("Invalid UTF-8 character")
|
||||
end
|
||||
|
||||
return 4
|
||||
|
||||
else
|
||||
error("Invalid UTF-8 character")
|
||||
end
|
||||
end
|
||||
|
||||
-- returns the number of characters in a UTF-8 string
|
||||
local function utf8len (s)
|
||||
-- argument checking
|
||||
if type(s) ~= "string" then
|
||||
for k,v in pairs(s) do print('"',tostring(k),'"',tostring(v),'"') end
|
||||
error("bad argument #1 to 'utf8len' (string expected, got ".. type(s).. ")")
|
||||
end
|
||||
|
||||
local pos = 1
|
||||
local bytes = len(s)
|
||||
local len = 0
|
||||
|
||||
while pos <= bytes do
|
||||
len = len + 1
|
||||
pos = pos + utf8charbytes(s, pos)
|
||||
end
|
||||
|
||||
return len
|
||||
end
|
||||
|
||||
-- functions identically to string.sub except that i and j are UTF-8 characters
|
||||
-- instead of bytes
|
||||
local function utf8sub (s, i, j)
|
||||
-- argument defaults
|
||||
j = j or -1
|
||||
|
||||
local pos = 1
|
||||
local bytes = len(s)
|
||||
local len = 0
|
||||
|
||||
-- only set l if i or j is negative
|
||||
local l = (i >= 0 and j >= 0) or utf8len(s)
|
||||
local startChar = (i >= 0) and i or l + i + 1
|
||||
local endChar = (j >= 0) and j or l + j + 1
|
||||
|
||||
-- can't have start before end!
|
||||
if startChar > endChar then
|
||||
return ""
|
||||
end
|
||||
|
||||
-- byte offsets to pass to string.sub
|
||||
local startByte,endByte = 1,bytes
|
||||
|
||||
while pos <= bytes do
|
||||
len = len + 1
|
||||
|
||||
if len == startChar then
|
||||
startByte = pos
|
||||
end
|
||||
|
||||
pos = pos + utf8charbytes(s, pos)
|
||||
|
||||
if len == endChar then
|
||||
endByte = pos - 1
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if startChar > len then startByte = bytes+1 end
|
||||
if endChar < 1 then endByte = 0 end
|
||||
|
||||
return sub(s, startByte, endByte)
|
||||
end
|
||||
|
||||
|
||||
-- replace UTF-8 characters based on a mapping table
|
||||
local function utf8replace (s, mapping)
|
||||
-- argument checking
|
||||
if type(s) ~= "string" then
|
||||
error("bad argument #1 to 'utf8replace' (string expected, got ".. type(s).. ")")
|
||||
end
|
||||
if type(mapping) ~= "table" then
|
||||
error("bad argument #2 to 'utf8replace' (table expected, got ".. type(mapping).. ")")
|
||||
end
|
||||
|
||||
local pos = 1
|
||||
local bytes = len(s)
|
||||
local charbytes
|
||||
local newstr = ""
|
||||
|
||||
while pos <= bytes do
|
||||
charbytes = utf8charbytes(s, pos)
|
||||
local c = sub(s, pos, pos + charbytes - 1)
|
||||
|
||||
newstr = newstr .. (mapping[c] or c)
|
||||
|
||||
pos = pos + charbytes
|
||||
end
|
||||
|
||||
return newstr
|
||||
end
|
||||
|
||||
|
||||
-- identical to string.upper except it knows about unicode simple case conversions
|
||||
local function utf8upper (s)
|
||||
return utf8replace(s, utf8_lc_uc)
|
||||
end
|
||||
|
||||
-- identical to string.lower except it knows about unicode simple case conversions
|
||||
local function utf8lower (s)
|
||||
return utf8replace(s, utf8_uc_lc)
|
||||
end
|
||||
|
||||
-- identical to string.reverse except that it supports UTF-8
|
||||
local function utf8reverse (s)
|
||||
-- argument checking
|
||||
if type(s) ~= "string" then
|
||||
error("bad argument #1 to 'utf8reverse' (string expected, got ".. type(s).. ")")
|
||||
end
|
||||
|
||||
local bytes = len(s)
|
||||
local pos = bytes
|
||||
local charbytes
|
||||
local newstr = ""
|
||||
|
||||
while pos > 0 do
|
||||
c = s:byte(pos)
|
||||
while c >= 128 and c <= 191 do
|
||||
pos = pos - 1
|
||||
c = s:byte(pos)
|
||||
end
|
||||
|
||||
charbytes = utf8charbytes(s, pos)
|
||||
|
||||
newstr = newstr .. sub(s, pos, pos + charbytes - 1)
|
||||
|
||||
pos = pos - 1
|
||||
end
|
||||
|
||||
return newstr
|
||||
end
|
||||
|
||||
-- http://en.wikipedia.org/wiki/Utf8
|
||||
-- http://developer.coronalabs.com/code/utf-8-conversion-utility
|
||||
local function utf8char(unicode)
|
||||
if unicode <= 0x7F then return char(unicode) end
|
||||
|
||||
if (unicode <= 0x7FF) then
|
||||
local Byte0 = 0xC0 + math.floor(unicode / 0x40);
|
||||
local Byte1 = 0x80 + (unicode % 0x40);
|
||||
return char(Byte0, Byte1);
|
||||
end;
|
||||
|
||||
if (unicode <= 0xFFFF) then
|
||||
local Byte0 = 0xE0 + math.floor(unicode / 0x1000);
|
||||
local Byte1 = 0x80 + (math.floor(unicode / 0x40) % 0x40);
|
||||
local Byte2 = 0x80 + (unicode % 0x40);
|
||||
return char(Byte0, Byte1, Byte2);
|
||||
end;
|
||||
|
||||
if (unicode <= 0x10FFFF) then
|
||||
local code = unicode
|
||||
local Byte3= 0x80 + (code % 0x40);
|
||||
code = math.floor(code / 0x40)
|
||||
local Byte2= 0x80 + (code % 0x40);
|
||||
code = math.floor(code / 0x40)
|
||||
local Byte1= 0x80 + (code % 0x40);
|
||||
code = math.floor(code / 0x40)
|
||||
local Byte0= 0xF0 + code;
|
||||
|
||||
return char(Byte0, Byte1, Byte2, Byte3);
|
||||
end;
|
||||
|
||||
error 'Unicode cannot be greater than U+10FFFF!'
|
||||
end
|
||||
|
||||
local shift_6 = 2^6
|
||||
local shift_12 = 2^12
|
||||
local shift_18 = 2^18
|
||||
|
||||
local utf8unicode
|
||||
utf8unicode = function(str, i, j, byte_pos)
|
||||
i = i or 1
|
||||
j = j or i
|
||||
|
||||
if i > j then return end
|
||||
|
||||
local char,bytes
|
||||
|
||||
if byte_pos then
|
||||
bytes = utf8charbytes(str,byte_pos)
|
||||
char = sub(str,byte_pos,byte_pos-1+bytes)
|
||||
else
|
||||
char,byte_pos = utf8sub(str,i,i)
|
||||
bytes = #char
|
||||
end
|
||||
|
||||
local unicode
|
||||
|
||||
if bytes == 1 then unicode = string.byte(char) end
|
||||
if bytes == 2 then
|
||||
local byte0,byte1 = string.byte(char,1,2)
|
||||
local code0,code1 = byte0-0xC0,byte1-0x80
|
||||
unicode = code0*shift_6 + code1
|
||||
end
|
||||
if bytes == 3 then
|
||||
local byte0,byte1,byte2 = string.byte(char,1,3)
|
||||
local code0,code1,code2 = byte0-0xE0,byte1-0x80,byte2-0x80
|
||||
unicode = code0*shift_12 + code1*shift_6 + code2
|
||||
end
|
||||
if bytes == 4 then
|
||||
local byte0,byte1,byte2,byte3 = string.byte(char,1,4)
|
||||
local code0,code1,code2,code3 = byte0-0xF0,byte1-0x80,byte2-0x80,byte3-0x80
|
||||
unicode = code0*shift_18 + code1*shift_12 + code2*shift_6 + code3
|
||||
end
|
||||
|
||||
return unicode,utf8unicode(str, i+1, j, byte_pos+bytes)
|
||||
end
|
||||
|
||||
-- Returns an iterator which returns the next substring and its byte interval
|
||||
local function utf8gensub(str, sub_len)
|
||||
sub_len = sub_len or 1
|
||||
local byte_pos = 1
|
||||
local len = #str
|
||||
return function()
|
||||
local char_count = 0
|
||||
local start = byte_pos
|
||||
repeat
|
||||
if byte_pos > len then return end
|
||||
char_count = char_count + 1
|
||||
local bytes = utf8charbytes(str,byte_pos)
|
||||
byte_pos = byte_pos+bytes
|
||||
|
||||
until char_count == sub_len
|
||||
|
||||
local last = byte_pos-1
|
||||
local sub = sub(str,start,last)
|
||||
return sub, start, last
|
||||
end
|
||||
end
|
||||
|
||||
string.len = utf8len
|
||||
string.sub = utf8sub
|
||||
string.reverse = utf8reverse
|
||||
string.char = utf8char
|
||||
string.unicode = utf8unicode
|
||||
string.gensub = utf8gensub
|
@ -333,6 +333,42 @@ function newobject:Scroll(amount)
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
- func: ScrollTo(position)
|
||||
- desc: scrolls the object
|
||||
--]]---------------------------------------------------------
|
||||
function newobject:ScrollTo(position)
|
||||
|
||||
local bartype = self.bartype
|
||||
local listo = self.parent.parent.parent
|
||||
local onscroll = listo.OnScroll
|
||||
|
||||
if bartype == "vertical" then
|
||||
local maxRealPos = self.parent.height - self.height
|
||||
if position > 1 then
|
||||
self.staticy = maxRealPos
|
||||
elseif position < 0 then
|
||||
self.staticy = 0
|
||||
else
|
||||
self.staticy = position * maxRealPos
|
||||
end
|
||||
elseif bartype == "horizontal" then
|
||||
local maxRealPos = self.parent.width - self.width
|
||||
if position > 1 then
|
||||
self.staticx = maxRealPos
|
||||
elseif position < 0 then
|
||||
self.staticx = 0
|
||||
else
|
||||
self.staticx = position * maxRealPos
|
||||
end
|
||||
end
|
||||
|
||||
if onscroll then
|
||||
onscroll(listo)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
- func: IsDragging()
|
||||
- desc: gets whether the object is being dragged or not
|
||||
|
@ -156,6 +156,19 @@ function newobject:update(dt)
|
||||
self.y = parent.y + self.staticy
|
||||
end
|
||||
|
||||
-- resize to parent
|
||||
if parent ~= base then
|
||||
if self.bartype == "vertical" then
|
||||
self.height = self.parent.height
|
||||
self.staticx = self.parent.width - self.width
|
||||
if parent.hbar then self.height = self.height - parent:GetHorizontalScrollBody().height end
|
||||
elseif self.bartype == "horizontal" then
|
||||
self.width = self.parent.width
|
||||
self.staticy = self.parent.height - self.height
|
||||
if parent.vbar then self.width = self.width - parent:GetVerticalScrollBody().width end
|
||||
end
|
||||
end
|
||||
|
||||
for k, v in ipairs(internals) do
|
||||
v:update(dt)
|
||||
end
|
||||
|
@ -320,10 +320,10 @@ function newobject:SetText(t)
|
||||
local key = k
|
||||
if width > maxw then
|
||||
table.remove(self.formattedtext, k)
|
||||
for n=1, #data do
|
||||
for n=1, string.len(data) do
|
||||
local item = data:sub(n, n)
|
||||
local itemw = v.font:getWidth(item)
|
||||
if n ~= #data then
|
||||
if n ~= string.len(data) then
|
||||
if (curw + itemw) > maxw then
|
||||
table.insert(inserts, {
|
||||
key = key,
|
||||
@ -393,7 +393,7 @@ function newobject:SetText(t)
|
||||
local text = v.text
|
||||
local color = v.color
|
||||
if detectlinks then
|
||||
if #text > 7 and (text:sub(1, 7) == "http://" or text:sub(1, 8) == "https://") then
|
||||
if string.len(text) > 7 and (text:sub(1, 7) == "http://" or text:sub(1, 8) == "https://") then
|
||||
v.link = true
|
||||
end
|
||||
end
|
||||
|
@ -341,6 +341,7 @@ function newobject:mousepressed(x, y, button)
|
||||
|
||||
local hover = self.hover
|
||||
local internals = self.internals
|
||||
local alt = love.keyboard.isDown("lalt", "ralt")
|
||||
local vbar = self.vbar
|
||||
local hbar = self.hbar
|
||||
local scrollamount = self.mousewheelscrollamount
|
||||
@ -381,26 +382,36 @@ function newobject:mousepressed(x, y, button)
|
||||
baseparent:MakeTop()
|
||||
end
|
||||
elseif button == "wu" then
|
||||
if vbar and not hbar then
|
||||
local vbar = self:GetVerticalScrollBody().internals[1].internals[1]
|
||||
vbar:Scroll(-scrollamount)
|
||||
elseif vbar and hbar then
|
||||
local vbar = self:GetVerticalScrollBody().internals[1].internals[1]
|
||||
vbar:Scroll(-scrollamount)
|
||||
elseif not vbar and hbar then
|
||||
local hbar = self:GetHorizontalScrollBody().internals[1].internals[1]
|
||||
hbar:Scroll(-scrollamount)
|
||||
if not alt then
|
||||
if focus then
|
||||
self.line = math.max(self.line - scrollamount, 1)
|
||||
elseif vbar then
|
||||
local vbar = self:GetVerticalScrollBody().internals[1].internals[1]
|
||||
vbar:Scroll(-scrollamount)
|
||||
end
|
||||
else
|
||||
if focus then
|
||||
self:MoveIndicator(-scrollamount)
|
||||
elseif hbar then
|
||||
local hbar = self:GetHorizontalScrollBody().internals[1].internals[1]
|
||||
hbar:Scroll(-scrollamount)
|
||||
end
|
||||
end
|
||||
elseif button == "wd" then
|
||||
if vbar and not hbar then
|
||||
local vbar = self:GetVerticalScrollBody().internals[1].internals[1]
|
||||
vbar:Scroll(scrollamount)
|
||||
elseif vbar and hbar then
|
||||
local vbar = self:GetVerticalScrollBody().internals[1].internals[1]
|
||||
vbar:Scroll(scrollamount)
|
||||
elseif not vbar and hbar then
|
||||
local hbar = self:GetHorizontalScrollBody().internals[1].internals[1]
|
||||
hbar:Scroll(scrollamount)
|
||||
if not alt then
|
||||
if focus then
|
||||
self.line = math.min(self.line + scrollamount, #self.lines)
|
||||
elseif vbar then
|
||||
local vbar = self:GetVerticalScrollBody().internals[1].internals[1]
|
||||
vbar:Scroll(scrollamount)
|
||||
end
|
||||
else
|
||||
if focus then
|
||||
self:MoveIndicator(scrollamount)
|
||||
elseif hbar then
|
||||
local hbar = self:GetHorizontalScrollBody().internals[1].internals[1]
|
||||
hbar:Scroll(scrollamount)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
@ -595,7 +606,7 @@ function newobject:RunKey(key, istext)
|
||||
if indicatornum == 0 then
|
||||
if line > 1 then
|
||||
self.line = line - 1
|
||||
local numchars = #lines[self.line]
|
||||
local numchars = string.len(lines[self.line])
|
||||
self:MoveIndicator(numchars)
|
||||
end
|
||||
else
|
||||
@ -613,14 +624,14 @@ function newobject:RunKey(key, istext)
|
||||
if not multiline then
|
||||
self:MoveIndicator(1)
|
||||
local indicatorx = self.indicatorx
|
||||
if indicatorx >= (x + swidth) and indicatornum ~= #text then
|
||||
if indicatorx >= (x + swidth) and indicatornum ~= string.len(text) then
|
||||
local width = font:getWidth(text:sub(indicatornum, indicatornum))
|
||||
self.offsetx = offsetx + width
|
||||
elseif indicatornum == #text and offsetx ~= ((font:getWidth(text)) - swidth + 10) and font:getWidth(text) + textoffsetx > swidth then
|
||||
elseif indicatornum == string.len(text) and offsetx ~= ((font:getWidth(text)) - swidth + 10) and font:getWidth(text) + textoffsetx > swidth then
|
||||
self.offsetx = ((font:getWidth(text)) - swidth + 10)
|
||||
end
|
||||
else
|
||||
if indicatornum == #text then
|
||||
if indicatornum == string.len(text) then
|
||||
if line < numlines then
|
||||
self.line = line + 1
|
||||
self:MoveIndicator(0, true)
|
||||
@ -631,7 +642,7 @@ function newobject:RunKey(key, istext)
|
||||
end
|
||||
if alltextselected then
|
||||
self.line = #lines
|
||||
self.indicatornum = lines[#lines]:len()
|
||||
self.indicatornum = string.len(lines[#lines])
|
||||
self.alltextselected = false
|
||||
end
|
||||
return
|
||||
@ -639,8 +650,8 @@ function newobject:RunKey(key, istext)
|
||||
if multiline then
|
||||
if line > 1 then
|
||||
self.line = line - 1
|
||||
if indicatornum > #lines[self.line] then
|
||||
self.indicatornum = #lines[self.line]
|
||||
if indicatornum > string.len(lines[self.line]) then
|
||||
self.indicatornum = string.len(lines[self.line])
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -649,8 +660,8 @@ function newobject:RunKey(key, istext)
|
||||
if multiline then
|
||||
if line < #lines then
|
||||
self.line = line + 1
|
||||
if indicatornum > #lines[self.line] then
|
||||
self.indicatornum = #lines[self.line]
|
||||
if indicatornum > string.len(lines[self.line]) then
|
||||
self.indicatornum = string.len(lines[self.line])
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -680,12 +691,12 @@ function newobject:RunKey(key, istext)
|
||||
local oldtext = lines[line]
|
||||
table.remove(lines, line)
|
||||
self.line = line - 1
|
||||
if #oldtext > 0 then
|
||||
newindicatornum = #lines[self.line]
|
||||
if string.len(oldtext) > 0 then
|
||||
newindicatornum = string.len(lines[self.line])
|
||||
lines[self.line] = lines[self.line] .. oldtext
|
||||
self:MoveIndicator(newindicatornum)
|
||||
else
|
||||
self:MoveIndicator(#lines[self.line])
|
||||
self:MoveIndicator(string.len(lines[self.line]))
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -693,9 +704,9 @@ function newobject:RunKey(key, istext)
|
||||
local cwidth = 0
|
||||
if masked then
|
||||
local maskchar = self.maskchar
|
||||
cwidth = font:getWidth(text:sub(#text):gsub(".", maskchar))
|
||||
cwidth = font:getWidth(text:sub(string.len(text)):gsub(".", maskchar))
|
||||
else
|
||||
cwidth = font:getWidth(text:sub(#text))
|
||||
cwidth = font:getWidth(text:sub(string.len(text)))
|
||||
end
|
||||
if self.offsetx > 0 then
|
||||
self.offsetx = self.offsetx - cwidth
|
||||
@ -713,13 +724,13 @@ function newobject:RunKey(key, istext)
|
||||
self.alltextselected = false
|
||||
indicatornum = self.indicatornum
|
||||
else
|
||||
if text ~= "" and indicatornum < #text then
|
||||
if text ~= "" and indicatornum < string.len(text) then
|
||||
text = self:RemoveFromText(indicatornum + 1)
|
||||
lines[line] = text
|
||||
elseif indicatornum == #text and line < #lines then
|
||||
elseif indicatornum == string.len(text) and line < #lines then
|
||||
local oldtext = lines[line + 1]
|
||||
if #oldtext > 0 then
|
||||
newindicatornum = #lines[self.line]
|
||||
if string.len(oldtext) > 0 then
|
||||
newindicatornum = string.len(lines[self.line])
|
||||
lines[self.line] = lines[self.line] .. oldtext
|
||||
end
|
||||
table.remove(lines, line + 1)
|
||||
@ -743,8 +754,8 @@ function newobject:RunKey(key, istext)
|
||||
if indicatornum == 0 then
|
||||
newtext = self.lines[line]
|
||||
self.lines[line] = ""
|
||||
elseif indicatornum > 0 and indicatornum < #self.lines[line] then
|
||||
newtext = self.lines[line]:sub(indicatornum + 1, #self.lines[line])
|
||||
elseif indicatornum > 0 and indicatornum < string.len(self.lines[line]) then
|
||||
newtext = self.lines[line]:sub(indicatornum + 1, string.len(self.lines[line]))
|
||||
self.lines[line] = self.lines[line]:sub(1, indicatornum)
|
||||
end
|
||||
if line ~= #lines then
|
||||
@ -766,14 +777,14 @@ function newobject:RunKey(key, istext)
|
||||
end
|
||||
ckey = key
|
||||
self.lines[self.line] = self:AddIntoText(self.tabreplacement, self.indicatornum)
|
||||
self:MoveIndicator(#self.tabreplacement)
|
||||
self:MoveIndicator(string.len(self.tabreplacement))
|
||||
end
|
||||
else
|
||||
if not editable then
|
||||
return
|
||||
end
|
||||
-- do not continue if the text limit has been reached or exceeded
|
||||
if #text >= self.limit and self.limit ~= 0 and not alltextselected then
|
||||
if string.len(text) >= self.limit and self.limit ~= 0 and not alltextselected then
|
||||
return
|
||||
end
|
||||
-- check for unusable characters
|
||||
@ -808,11 +819,11 @@ function newobject:RunKey(key, istext)
|
||||
lines = self.lines
|
||||
line = self.line
|
||||
end
|
||||
if indicatornum ~= 0 and indicatornum ~= #text then
|
||||
if indicatornum ~= 0 and indicatornum ~= string.len(text) then
|
||||
text = self:AddIntoText(key, indicatornum)
|
||||
lines[line] = text
|
||||
self:MoveIndicator(1)
|
||||
elseif indicatornum == #text then
|
||||
elseif indicatornum == string.len(text) then
|
||||
text = text .. key
|
||||
lines[line] = text
|
||||
self:MoveIndicator(1)
|
||||
@ -871,8 +882,8 @@ function newobject:MoveIndicator(num, exact)
|
||||
self.indicatornum = num
|
||||
end
|
||||
|
||||
if self.indicatornum > #text then
|
||||
self.indicatornum = #text
|
||||
if self.indicatornum > string.len(text) then
|
||||
self.indicatornum = string.len(text)
|
||||
elseif self.indicatornum < 0 then
|
||||
self.indicatornum = 0
|
||||
end
|
||||
@ -941,6 +952,55 @@ function newobject:UpdateIndicator()
|
||||
self.indicatory = texty
|
||||
end
|
||||
|
||||
-- indicator should be visible, so correcting scrolls
|
||||
if self.focus then
|
||||
local indicatorRelativeX = width + self.textoffsetx - self.offsetx
|
||||
local leftlimit, rightlimit = 1, self:GetWidth() - 1
|
||||
if self.linenumberspanel then
|
||||
rightlimit = rightlimit - self:GetLineNumbersPanel().width
|
||||
end
|
||||
if self.vbar then
|
||||
rightlimit = rightlimit - self:GetVerticalScrollBody().width
|
||||
end
|
||||
if not (indicatorRelativeX > leftlimit and indicatorRelativeX < rightlimit) then
|
||||
local hbody = self:GetHorizontalScrollBody()
|
||||
if hbody then
|
||||
local twidth = 0
|
||||
for k, v in ipairs(lines) do
|
||||
local linewidth = 0
|
||||
if self.masked then
|
||||
linewidth = font:getWidth(v:gsub(".", self.maskchar))
|
||||
else
|
||||
linewidth = font:getWidth(v)
|
||||
end
|
||||
if linewidth > twidth then
|
||||
twidth = linewidth
|
||||
end
|
||||
end
|
||||
local correction = self:GetWidth() / 8
|
||||
if indicatorRelativeX < leftlimit then
|
||||
correction = correction * -1
|
||||
end
|
||||
hbody:GetScrollBar():ScrollTo((width + correction) / twidth)
|
||||
end
|
||||
end
|
||||
local indicatorRelativeY = (line - 1) * theight + self.textoffsety - self.offsety
|
||||
local uplimit, downlimit = theight, self:GetHeight() - theight
|
||||
if self.hbar then
|
||||
downlimit = downlimit - self:GetHorizontalScrollBody().height
|
||||
end
|
||||
if not (indicatorRelativeY > uplimit and indicatorRelativeY < downlimit) then
|
||||
local vbody = self:GetVerticalScrollBody()
|
||||
if vbody then
|
||||
local correction = self:GetHeight() / 8 / theight
|
||||
if indicatorRelativeY < uplimit then
|
||||
correction = correction * -1
|
||||
end
|
||||
vbody:GetScrollBar():ScrollTo((line - 1 + correction)/#lines)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
|
||||
end
|
||||
@ -1029,7 +1089,7 @@ function newobject:GetTextCollisions(x, y)
|
||||
end
|
||||
local line = self.line
|
||||
local curline = lines[line]
|
||||
for i=1, #curline do
|
||||
for i=1, string.len(curline) do
|
||||
local char = text:sub(i, i)
|
||||
local width = 0
|
||||
if masked then
|
||||
@ -1049,7 +1109,7 @@ function newobject:GetTextCollisions(x, y)
|
||||
self:MoveIndicator(i - 1, true)
|
||||
break
|
||||
else
|
||||
self.indicatornum = #curline
|
||||
self.indicatornum = string.len(curline)
|
||||
end
|
||||
|
||||
if x < tx then
|
||||
@ -1057,16 +1117,16 @@ function newobject:GetTextCollisions(x, y)
|
||||
end
|
||||
|
||||
if x > (tx + width) then
|
||||
self:MoveIndicator(#curline, true)
|
||||
self:MoveIndicator(string.len(curline), true)
|
||||
end
|
||||
end
|
||||
|
||||
if #curline == 0 then
|
||||
if string.len(curline) == 0 then
|
||||
self.indicatornum = 0
|
||||
end
|
||||
end
|
||||
else
|
||||
for i=1, #text do
|
||||
for i=1, string.len(text) do
|
||||
local char = text:sub(i, i)
|
||||
local width = 0
|
||||
if masked then
|
||||
@ -1088,7 +1148,7 @@ function newobject:GetTextCollisions(x, y)
|
||||
self:MoveIndicator(0, true)
|
||||
end
|
||||
if x > (tx + width) then
|
||||
self:MoveIndicator(#text, true)
|
||||
self:MoveIndicator(string.len(text), true)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1318,13 +1378,13 @@ function newobject:SetText(text)
|
||||
self.lines = {""}
|
||||
end
|
||||
self.line = #self.lines
|
||||
self.indicatornum = #self.lines[#self.lines]
|
||||
self.indicatornum = string.len(self.lines[#self.lines])
|
||||
else
|
||||
text = text:gsub(string.char(92) .. string.char(110), "")
|
||||
text = text:gsub(string.char(10), "")
|
||||
self.lines = {text}
|
||||
self.line = 1
|
||||
self.indicatornum = #text
|
||||
self.indicatornum = string.len(text)
|
||||
end
|
||||
|
||||
return self
|
||||
|
@ -1681,18 +1681,23 @@ function skin.DrawColumnListRow(object)
|
||||
love.graphics.rectangle("fill", x, y, width, height)
|
||||
end
|
||||
|
||||
love.graphics.setFont(font)
|
||||
if selected then
|
||||
love.graphics.setColor(textselectedcolor)
|
||||
elseif hover then
|
||||
love.graphics.setColor(texthovercolor)
|
||||
else
|
||||
love.graphics.setColor(textcolor)
|
||||
end
|
||||
for k, v in ipairs(columndata) do
|
||||
love.graphics.setFont(font)
|
||||
local text = ParseRowText(v, x, parent.parent:GetColumnWidth(k), x, textx)
|
||||
if selected then
|
||||
love.graphics.setColor(textselectedcolor)
|
||||
elseif hover then
|
||||
love.graphics.setColor(texthovercolor)
|
||||
local rwidth = parent.parent:GetColumnWidth(k)
|
||||
if rwidth then
|
||||
local text = ParseRowText(v, x, rwidth, x, textx)
|
||||
love.graphics.print(text, x + textx, y + texty)
|
||||
x = x + parent.parent.children[k]:GetWidth()
|
||||
else
|
||||
love.graphics.setColor(textcolor)
|
||||
break
|
||||
end
|
||||
love.graphics.print(text, x + textx, y + texty)
|
||||
x = x + parent.parent.children[k]:GetWidth()
|
||||
end
|
||||
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user