LoveFrames/objects/text.lua
Kenny Shields 6d59ccc879 new tooltip methods and clipboard support
added tooltip method SetOffsetX(offsetx)
added tooltip method SetOffsetY(offsety)
added basic clipboard support for the textinput object (0.9.0 only)
fixed text object width issues
fixed an error caused by pressing a function key while a textinput
object was focused
fixed the tooltip object not setting the state of its text object
cleaned up the tooltip object
modified textinput:RunKey to account for changes in the 0.9.0 api
2013-09-14 11:37:01 -04:00

595 lines
14 KiB
Lua

--[[------------------------------------------------
-- Love Frames - A GUI library for LOVE --
-- Copyright (c) 2013 Kenny Shields --
--]]------------------------------------------------
--[[------------------------------------------------
-- note: the text wrapping of this object is
experimental and not final
--]]------------------------------------------------
-- text class
local newobject = loveframes.NewObject("text", "loveframes_object_text", true)
--[[---------------------------------------------------------
- func: initialize()
- desc: initializes the object
--]]---------------------------------------------------------
function newobject:initialize()
self.type = "text"
self.text = ""
self.font = loveframes.basicfont
self.width = 5
self.height = 5
self.maxw = 0
self.shadowxoffset = 1
self.shadowyoffset = 1
self.formattedtext = {}
self.original = {}
self.defaultcolor = {0, 0, 0, 255}
self.shadowcolor = {0, 0, 0, 255}
self.ignorenewlines = false
self.shadow = false
self.internal = false
end
--[[---------------------------------------------------------
- func: update(deltatime)
- desc: updates the object
--]]---------------------------------------------------------
function newobject:update(dt)
local state = loveframes.state
local selfstate = self.state
if state ~= selfstate then
return
end
local visible = self.visible
local alwaysupdate = self.alwaysupdate
if not visible then
if not alwaysupdate then
return
end
end
local parent = self.parent
local base = loveframes.base
local update = self.Update
self:CheckHover()
-- move to parent if there is a parent
if parent ~= base then
self.x = self.parent.x + self.staticx
self.y = self.parent.y + self.staticy
end
if update then
update(self, dt)
end
end
--[[---------------------------------------------------------
- func: draw()
- desc: draws the object
--]]---------------------------------------------------------
function newobject:draw()
local state = loveframes.state
local selfstate = self.state
if state ~= selfstate then
return
end
if not self.visible then
return
end
local skins = loveframes.skins.available
local skinindex = loveframes.config["ACTIVESKIN"]
local defaultskin = loveframes.config["DEFAULTSKIN"]
local selfskin = self.skin
local skin = skins[selfskin] or skins[skinindex]
local drawfunc = skin.DrawText or skins[defaultskin].DrawText
local draw = self.Draw
local drawcount = loveframes.drawcount
-- set the object's draw order
self:SetDrawOrder()
if draw then
draw(self)
else
drawfunc(self)
end
self:DrawText()
end
--[[---------------------------------------------------------
- func: mousepressed(x, y, button)
- desc: called when the player presses a mouse button
--]]---------------------------------------------------------
function newobject:mousepressed(x, y, button)
local state = loveframes.state
local selfstate = self.state
if state ~= selfstate then
return
end
local visible = self.visible
if not visible then
return
end
local hover = self.hover
if hover and button == "l" then
local baseparent = self:GetBaseParent()
if baseparent and baseparent.type == "frame" then
baseparent:MakeTop()
end
end
end
--[[---------------------------------------------------------
- func: SetText(text)
- desc: sets the object's text
--]]---------------------------------------------------------
function newobject:SetText(t)
local dtype = type(t)
local maxw = self.maxw
local font = self.font
local defaultcolor = self.defaultcolor
local inserts = {}
local prevfont = font
local tdata, prevcolor
self.text = ""
self.formattedtext = {}
if dtype == "string" then
tdata = {t}
self.original = {t}
elseif dtype == "number" then
tdata = {tostring(t)}
self.original = {tostring(t)}
elseif dtype == "table" then
tdata = t
self.original = t
else
return
end
for k, v in ipairs(tdata) do
dtype = type(v)
if k == 1 and dtype ~= "table" then
prevcolor = defaultcolor
end
if dtype == "table" then
prevcolor = v
elseif dtype == "userdata" then
prevfont = v
elseif dtype == "number" then
table.insert(self.formattedtext, {font = prevfont, color = prevcolor, text = tostring(v)})
elseif dtype == "string" then
if self.ignorenewlines then
v = v:gsub(" \n ", " ")
v = v:gsub("\n", "")
end
v = v:gsub(string.char(9), " ")
local parts = loveframes.util.SplitString(v, " ")
for i, j in ipairs(parts) do
table.insert(self.formattedtext, {font = prevfont, color = prevcolor, text = j})
end
end
end
if maxw > 0 then
for k, v in ipairs(self.formattedtext) do
local data = v.text
local width = v.font:getWidth(data)
local curw = 0
local new = ""
local key = k
if width > maxw then
table.remove(self.formattedtext, k)
for n=1, #data do
local item = data:sub(n, n)
local itemw = v.font:getWidth(item)
if n ~= #data then
if (curw + itemw) > maxw then
table.insert(inserts, {key = key, font = v.font, color = v.color, text = new})
new = item
curw = 0 + itemw
key = key + 1
else
new = new .. item
curw = curw + itemw
end
else
new = new .. item
table.insert(inserts, {key = key, font = v.font, color = v.color, text = new})
end
end
end
end
end
for k, v in ipairs(inserts) do
table.insert(self.formattedtext, v.key, {font = v.font, color = v.color, text = v.text})
end
local textdata = self.formattedtext
local maxw = self.maxw
local font = self.font
local twidth = 0
local drawx = 0
local drawy = 0
local lines = 0
local textwidth = 0
local lastwidth = 0
local totalwidth = 0
local x = self.x
local y = self.y
local prevtextwidth = 0
local prevtextheight = 0
local prevlargestheight = 0
local largestwidth = 0
local largestheight = 0
local initialwidth = 0
for k, v in ipairs(textdata) do
local text = v.text
local color = v.color
if type(text) == "string" then
self.text = self.text .. text
local width = v.font:getWidth(text)
local height = v.font:getHeight("a")
if height > largestheight then
largestheight = height
prevlargestheight = height
end
totalwidth = totalwidth + width
if maxw > 0 then
if k ~= 1 then
if string.byte(text) == 10 then
twidth = 0
drawx = 0
width = 0
drawy = drawy + largestheight
largestheight = 0
text = ""
elseif (twidth + width) > maxw then
twidth = 0 + width
drawx = 0
drawy = drawy + largestheight
largestheight = 0
else
twidth = twidth + width
drawx = drawx + prevtextwidth
end
else
twidth = twidth + width
end
prevtextwidth = width
prevtextheight = height
v.x = drawx
v.y = drawy
else
if k ~= 1 then
if string.byte(text) == 10 then
twidth = 0
drawx = 0
width = 0
drawy = drawy + largestheight
largestheight = 0
text = ""
if lastwidth < textwidth then
lastwidth = textwidth
end
if largestwidth < textwidth then
largestwidth = textwidth
end
textwidth = 0
else
drawx = drawx + prevtextwidth
textwidth = textwidth + width
end
else
initialwidth = width
end
prevtextwidth = width
prevtextheight = height
v.x = drawx
v.y = drawy
end
end
end
if lastwidth == 0 then
textwidth = totalwidth
end
if textwidth < largestwidth then
textwidth = largestwidth + initialwidth
end
if maxw > 0 then
self.width = maxw
else
self.width = textwidth
end
self.height = drawy + prevlargestheight
end
--[[---------------------------------------------------------
- func: GetText()
- desc: gets the object's text
--]]---------------------------------------------------------
function newobject:GetText()
return self.text
end
--[[---------------------------------------------------------
- func: GetFormattedText()
- desc: gets the object's formatted text
--]]---------------------------------------------------------
function newobject:GetFormattedText()
return self.formattedtext
end
--[[---------------------------------------------------------
- func: DrawText()
- desc: draws the object's text
--]]---------------------------------------------------------
function newobject:DrawText()
local textdata = self.formattedtext
local x = self.x
local y = self.y
local shadow = self.shadow
local shadowxoffset = self.shadowxoffset
local shadowyoffset = self.shadowyoffset
local shadowcolor = self.shadowcolor
local inlist, list = self:IsInList()
for k, v in ipairs(textdata) do
local text = v.text
local color = v.color
local font = v.font
local theight = font:getHeight("a")
if inlist then
if (y + v.y) <= (list.y + list.height) and self.y + ((v.y + theight)) >= list.y then
love.graphics.setFont(font)
if shadow then
love.graphics.setColor(unpack(shadowcolor))
love.graphics.print(text, x + v.x + shadowxoffset, y + v.y + shadowyoffset)
end
love.graphics.setColor(unpack(color))
love.graphics.print(text, x + v.x, y + v.y)
end
else
love.graphics.setFont(font)
if shadow then
love.graphics.setColor(unpack(shadowcolor))
love.graphics.print(text, x + v.x + shadowxoffset, y + v.y + shadowyoffset)
end
love.graphics.setColor(unpack(color))
love.graphics.print(text, x + v.x, y + v.y)
end
end
end
--[[---------------------------------------------------------
- func: SetMaxWidth(width)
- desc: sets the object's maximum width
--]]---------------------------------------------------------
function newobject:SetMaxWidth(width)
local original = self.original
self.maxw = width
self:SetText(original)
end
--[[---------------------------------------------------------
- func: GetMaxWidth()
- desc: gets the object's maximum width
--]]---------------------------------------------------------
function newobject:GetMaxWidth()
return self.maxw
end
--[[---------------------------------------------------------
- func: SetWidth(width)
- desc: sets the object's width
--]]---------------------------------------------------------
function newobject:SetWidth(width)
self:SetMaxWidth(width)
end
--[[---------------------------------------------------------
- func: SetHeight()
- desc: sets the object's height
--]]---------------------------------------------------------
function newobject:SetHeight(height)
return
end
--[[---------------------------------------------------------
- func: SetSize()
- desc: sets the object's size
--]]---------------------------------------------------------
function newobject:SetSize(width, height)
self:SetMaxWidth(width)
end
--[[---------------------------------------------------------
- func: SetFont(font)
- desc: sets the object's font
- note: font argument must be a font object
--]]---------------------------------------------------------
function newobject:SetFont(font)
local original = self.original
self.font = font
if original then
self:SetText(original)
end
end
--[[---------------------------------------------------------
- func: GetFont()
- desc: gets the object's font
--]]---------------------------------------------------------
function newobject:GetFont()
return self.font
end
--[[---------------------------------------------------------
- func: GetLines()
- desc: gets the number of lines the object's text uses
--]]---------------------------------------------------------
function newobject:GetLines()
return self.lines
end
--[[---------------------------------------------------------
- func: SetIgnoreNewlines(bool)
- desc: sets whether the object should ignore \n or not
--]]---------------------------------------------------------
function newobject:SetIgnoreNewlines(bool)
self.ignorenewlines = bool
end
--[[---------------------------------------------------------
- func: GetIgnoreNewlines()
- desc: gets whether the object should ignore \n or not
--]]---------------------------------------------------------
function newobject:GetIgnoreNewlines()
return self.ignorenewlines
end
--[[---------------------------------------------------------
- func: SetShadow(bool)
- desc: sets whether or not the object should draw a
shadow behind its text
--]]---------------------------------------------------------
function newobject:SetShadow(bool)
self.shadow = bool
end
--[[---------------------------------------------------------
- func: GetShadow()
- desc: gets whether or not the object should draw a
shadow behind its text
--]]---------------------------------------------------------
function newobject:GetShadow()
return self.shadow
end
--[[---------------------------------------------------------
- func: SetShadowOffsets(offsetx, offsety)
- desc: sets the object's x and y shadow offsets
--]]---------------------------------------------------------
function newobject:SetShadowOffsets(offsetx, offsety)
self.shadowxoffset = offsetx
self.shadowyoffset = offsety
end
--[[---------------------------------------------------------
- func: GetShadowOffsets()
- desc: gets the object's x and y shadow offsets
--]]---------------------------------------------------------
function newobject:GetShadowOffsets()
return self.shadowxoffset, self.shadowyoffset
end
--[[---------------------------------------------------------
- func: SetShadowColor(r, g, b, a)
- desc: sets the object's shadow color
--]]---------------------------------------------------------
function newobject:SetShadowColor(r, g, b, a)
self.shadowcolor = {r, g, b, a}
end
--[[---------------------------------------------------------
- func: GetShadowColor()
- desc: gets the object's shadow color
--]]---------------------------------------------------------
function newobject:GetShadowColor()
return self.shadowcolor
end
--[[---------------------------------------------------------
- func: SetDefaultColor(r, g, b, a)
- desc: sets the object's default text color
--]]---------------------------------------------------------
function newobject:SetDefaultColor(r, g, b, a)
self.defaultcolor = {r, g, b, a}
end
--[[---------------------------------------------------------
- func: GetDefaultColor()
- desc: gets the object's default text color
--]]---------------------------------------------------------
function newobject:GetDefaultColor()
return self.defaultcolor
end