WoWInterface SVN DotIt

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 13 to Rev 14
    Reverse comparison

Rev 13 → Rev 14

trunk/DotIt/libs/sbar.lua New file
0,0 → 1,1253
local major = "SBar-0.1"
local minor = 1
local DEBUG = true
local tinsert = table.insert
 
assert(LibStub, string.format("%s requires LibStub.", major))
 
local sbar = LibStub:NewLibrary(major, minor)
if( not sbar ) then return end
local scaleinfo
local default = {
texture = "Interface\\ChatFrame\\ChatFrameBackground"
}
 
local poolNum = 0
 
local newList, del, deepDel, deepCopy
do
local pool = setmetatable({}, {__mode='k'})
function newList(...)
poolNum = poolNum + 1
local t = next(pool)
if t then
pool[t] = nil
for i = 1, select('#', ...) do
t[i] = select(i, ...)
end
else
t = { ... }
end
return t
end
function del(t)
if type(t) ~= "table" then
error("Bad argument #1 to `del'. Expected table, got nil.", 2)
end
if pool[t] then
error("Double-free syndrome.", 2)
end
pool[t] = true
poolNum = poolNum - 1
for k in pairs(t) do
t[k] = nil
end
setmetatable(t, nil)
t[''] = true
t[''] = nil
 
 
return nil
end
local deepDel_data
function deepDel(tinp)
local t = tinp
tinp = nil
local made_deepDel_data = not deepDel_data
if made_deepDel_data then
deepDel_data = newList()
end
if type(t) == "table" and not deepDel_data[t] then
deepDel_data[t] = true
for k,v in pairs(t) do
deepDel(v)
deepDel(k)
end
del(t)
end
if made_deepDel_data then
deepDel_data = del(deepDel_data)
end
return nil
end
function deepCopy(t)
if type(t) ~= "table" then
return t
else
local u = newList()
for k, v in pairs(t) do
u[deepCopy(k)] = deepCopy(v)
end
return u
end
end
end
 
local function argcheck(param, num, ...)
for i = 1, select('#', ...) do
if(type(param) == select(i, ...)) then
return
end
end
local types = string.join(", ", ...)
local caller = string.match(debugstack(2,2,0), ": in function [`<](.-)['>]")
error(tostring("Bad argument %d in function %s. (%s instead of %s)"):format(num, caller, type(param), types))
end
 
--*-------------------------------------------
-- private methods
--*-------------------------------------------
local fixedText = newList()
local bars
 
local function clearFixedText(pos)
if not pos then return end
for _, bar in pairs(bars) do
if bar.pos and bar.pos == pos then
return
end
end
sbar:SetFixedText(nil, pos)
end
local function out(text)
if DEBUG then
DEFAULT_CHAT_FRAME:AddMessage(text)
end
end
local function setFont(obj, what)
if not scaleinfo.fonts then
obj:SetFont("Fonts\\FRIZQT__.TTF", 11, "OUTLINE, MONOCHROME")
end
local font, size, flags
if what == "scale" then
font = scaleinfo.fonts.scale.font
size = scaleinfo.fonts.scale.size
flags = ""
if scaleinfo.fonts.scale.outline then
flags = flags.."OUTLINE"
end
if scaleinfo.fonts.scale.thickoutline then
if flags == "" then
flags = flags.."THICKOUTLINE"
else
flags = flags..", THICKOUTLINE"
end
end
if scaleinfo.fonts.scale.monochrome then
if flags == "" then
flags = flags.."MONOCHROME"
else
flags = flags..", MONOCHROME"
end
end
else
font = scaleinfo.fonts.bar.font
size = scaleinfo.fonts.bar.size
flags = ""
if scaleinfo.fonts.bar.outline then
flags = flags.."OUTLINE"
end
if scaleinfo.fonts.bar.thickoutline then
if flags == "" then
flags = flags.."THICKOUTLINE"
else
flags = flags..", THICKOUTLINE"
end
end
if scaleinfo.fonts.bar.monochrome then
if flags == "" then
flags = flags.."MONOCHROME"
else
flags = flags..", MONOCHROME"
end
end
end
obj:SetFont(font, size, flags)
end
local function getPosition(frame)
return frame:GetLeft() * frame:GetEffectiveScale(), frame:GetBottom() * frame:GetEffectiveScale()
end
local function setPosition(frame, x, y)
frame:SetPoint("BOTTOMLEFT", x / frame:GetEffectiveScale(), y / frame:GetEffectiveScale())
end
local function strvert(str)
local outp = ""
for b in string.gmatch(str, "%w+") do
outp = outp .. b .. "\n"
end
outp = string.sub(outp, 1, string.len(outp)-1)
return outp
end
local function strvertret(str)
return string.join("", string.gmatch(str, "%w+"))
end
 
local function qsort(x,l,u,f)
if l<u then
local m=math.random(u-(l-1))+l-1 -- choose a random pivot in range l..u
x[l],x[m]=x[m],x[l] -- swap pivot to first position
local t=x[l] -- pivot value
m=l
local i=l+1
while i<=u do
-- invariant: x[l+1..m] < t <= x[m+1..i-1]
if f(x[i],t) then
m=m+1
x[m],x[i]=x[i],x[m] -- swap x[i] and x[m]
end
i=i+1
end
x[l],x[m]=x[m],x[l] -- swap pivot to a valid place
-- x[l+1..m-1] < x[m] <= x[m+1..u]
qsort(x,l,m-1,f)
qsort(x,m+1,u,f)
end
end
local function updateBarsFrameLevel(bartupd)
if not bartupd then return false end
local j, t
-- simple bubble sort
local n=1
while bartupd[n] do n=n+1 end; n=n-1
qsort(bartupd, 1, n, function(x, y) return (x.start+x.dur) < (y.start + y.dur) end)
 
 
--
local count = #bartupd + 2
local i = 1
while bartupd[i] do
count = count - 1
bartupd[i].frame:SetFrameLevel(count)
i = i + 1
end
del(bartupd)
end
--
local function checkLog()
if not scaleinfo.amaxtimes then return false end
local count = 0
for k, v in pairs(scaleinfo.amaxtimes) do
count = count + 1
end
if count == 0 then return false end
return true
end
local function OnVerticalUpdate(bars, el, maxneg, maxtime, loflag)
-- loop through all bars
if not bars then return end
local tmptime
for k, bar in pairs(bars) do
if bar.frame then
-- solves the truncating problem
local sekinp = scaleinfo.size / scaleinfo.maxtime
if not bar.start or not bar.dur then return end
if maxneg > bar.start then
 
bar.dur = bar.dur + (bar.start - maxneg)
bar.start = maxneg
end
if maxneg == bar.start then
if checkLog() and (bar.dur + bar.start) > scaleinfo.maxtime then
tmptime = bar.dur - el
bar.dur = scaleinfo.maxtime - bar.start
else
bar.dur = bar.dur - el
end
else
bar.start = bar.start - el
end
if checkLog() and (bar.dur + bar.start) > scaleinfo.maxtime then
tmptime = bar.dur
bar.dur = scaleinfo.maxtime - bar.start
end
--
if not loflag then
bar.frame:SetPoint("BOTTOMRIGHT", scaleinfo.frame, "BOTTOMLEFT", 8 - bar.pos * scaleinfo.height, sekinp*bar.start)
else
bar.frame:SetPoint("BOTTOMLEFT", scaleinfo.frame, "BOTTOMRIGHT", -8 + bar.pos * scaleinfo.height, sekinp*bar.start)
end
bar.frame:SetHeight(sekinp*bar.dur)
if bar.dur + bar.start <= 0 then
local wpos = bar.pos
tmppos = bar.pos
bar.pos = nil
clearFixedText(wpos)
bar.frame:Hide()
 
 
bar.frame = nil
bar.pos = nil
bar.dur = nil
bar.start = nil
 
bar.data = nil
deepDel(bar)
bar = nil
 
end
if bar then
if(bar.start < 0) then
if(math.abs(bar.start) < bar.dur) then
bar.tex:Show()
bar.texg:Show()
bar.tex:SetHeight(sekinp*(bar.dur-math.abs(bar.start)))
bar.texg:SetHeight(sekinp*math.abs(bar.start))
else
bar.tex:Hide()
bar.texg:Show()
bar.texg:SetHeight(bar.frame:GetWidth())
end
else
bar.tex:Show()
bar.texg:Hide()
bar.tex:SetHeight(sekinp*bar.dur)
end
end
 
if tmptime and checkLog() then
local count = 0
local mtime = scaleinfo.maxtime
local parttime
for k, v in pairs(scaleinfo.amaxtimes) do
mtime = mtime + v
parttime = v
if mtime > tmptime then break end
count = count + 1
end
-- we have count full bars and count + 1 is the bar that is not full
local partsekinp = scaleinfo.part / parttime
local timeinseg = tmptime - (mtime - parttime)
bar.frame:SetHeight(bar.frame:GetHeight() + scaleinfo.part * count + partsekinp * timeinseg)
bar.tex:SetHeight(bar.tex:GetHeight() + scaleinfo.part * count + partsekinp * timeinseg)
bar.dur = tmptime
end
tmptime = nil
end
end
--
end
 
local function OnHorizontalUpdate(bars, el, maxneg, loflag)
if not bars then return end
-- loop through all bars
local tmptime
for k, bar in pairs(bars) do
if bar.frame then
local sekinp = scaleinfo.size / scaleinfo.maxtime
-- solves the truncating problem
if not bar.start or not bar.dur then return end
if maxneg > bar.start then
bar.dur = bar.dur + (bar.start - maxneg)
bar.start = maxneg
end
if maxneg == bar.start then
if checkLog() and (bar.dur + bar.start) > scaleinfo.maxtime then
tmptime = bar.dur - el
bar.dur = scaleinfo.maxtime - bar.start
else
bar.dur = bar.dur - el
end
else
bar.start = bar.start - el
end
if checkLog() and (bar.dur + bar.start) > scaleinfo.maxtime then
tmptime = bar.dur
bar.dur = scaleinfo.maxtime - bar.start
end
--
-- bar.frame, bar.tex, bar.texg, bar.dur, bar.start, bar.pos, bar.icon, bar.text
--out(GetTime())
if not loflag then
bar.frame:SetPoint("BOTTOMLEFT", scaleinfo.frame, "TOPLEFT", sekinp*bar.start, -8 + bar.pos * scaleinfo.height)
else
bar.frame:SetPoint("TOPLEFT", scaleinfo.frame, "BOTTOMLEFT", sekinp*bar.start, 8 - bar.pos * scaleinfo.height)
end
bar.frame:SetWidth(sekinp*bar.dur)
if bar.dur + bar.start <= 0 then
local wpos = bar.pos
tmppos = bar.pos
bar.pos = nil
clearFixedText(wpos)
bar.frame:Hide()
 
 
bar.frame = nil
bar.pos = nil
bar.dur = nil
bar.start = nil
 
bar.data = nil
deepDel(bar)
bar = nil
end
if bar then
if(bar.start < 0) then
if(math.abs(bar.start) < bar.dur) then
bar.tex:Show()
bar.texg:Show()
bar.tex:SetWidth(sekinp*(bar.dur-math.abs(bar.start)))
bar.texg:SetWidth(sekinp*math.abs(bar.start))
else
bar.tex:Hide()
bar.texg:Show()
bar.texg:SetWidth(bar.frame:GetWidth())
end
else
bar.tex:Show()
bar.texg:Hide()
bar.tex:SetWidth(sekinp*bar.dur)
end
end
if tmptime and checkLog() then
local count = 0
local mtime = scaleinfo.maxtime
local parttime
for k, v in pairs(scaleinfo.amaxtimes) do
mtime = mtime + v
parttime = v
if mtime > tmptime then break end
count = count + 1
end
-- we have count full bars and count + 1 is the bar that is not full
local partsekinp = scaleinfo.part / parttime
local timeinseg = tmptime - (mtime - parttime)
bar.frame:SetWidth(bar.frame:GetWidth() + scaleinfo.part * count + partsekinp * timeinseg)
bar.tex:SetWidth(bar.tex:GetWidth() + scaleinfo.part * count + partsekinp * timeinseg)
bar.dur = tmptime
end
tmptime = nil
end
 
end
--
end
--
local el = 0
local function OnUpdate(self, elapsed)
el = el + elapsed
--if el < 1 then return end
local count = 0
if bars then
for k, bar in pairs(bars) do
if bar.frame then
count = count + 1
end
end
end
if count == 0 then
if scaleinfo.hide and scaleinfo.frame:IsShown() then
scaleinfo.frame:Hide()
end
el = 0
scaleinfo.frame:SetScript("OnUpdate", nil)
return
end
if scaleinfo.horizontal then
OnHorizontalUpdate(bars, el, scaleinfo.maxneg, scaleinfo.loflag)
else
OnVerticalUpdate(bars, el, scaleinfo.maxneg, scaleinfo.maxtime, scaleinfo.loflag)
end
el = 0
sbar:UpdateFrameLevel()
end
local function createVericalScale(height, maxtime, steps, handler, loflag, texture)
local secforstep = maxtime / steps
 
local f = CreateFrame("Frame", "SBarAnchorFrame",UIParent) -- only used for the scale
f:EnableMouse(true)
f:SetMovable(true)
f:SetFrameStrata("BACKGROUND")
f:SetWidth(32)
f:SetHeight(height)
f:SetPoint("CENTER",UIParent,"CENTER",0,0)
f:Show()
local function OnDragStart(self)
if not scaleinfo.locked then
if( IsAltKeyDown() ) then
self.isMoving = true
self:StartMoving()
end
end
end
local function OnDragStop(self)
if( self.isMoving) then
self:StopMovingOrSizing()
end
if type(handler) == "function" then
handler()
else
if handler then
local x, y = getPosition(scaleinfo.frame)
handler.x = x
handler.y = y
end
end
end
 
f:SetScript("OnMouseDown", OnDragStart)
f:SetScript("OnMouseUp", OnDragStop)
 
local maintexture = f:CreateTexture(nil, "BACKGROUND")
maintexture:SetTexture(texture or default.texture)
maintexture:SetPoint("CENTER", 0, -1)
maintexture:SetWidth(2)
maintexture:SetHeight(f:GetHeight())
maintexture:SetVertexColor(1, 1, 1, 1)
 
local part = f:GetHeight() / steps
for i = 0, steps do
local font
if scaleinfo.scaletext then
font = f:CreateFontString()
setFont(font, "scale")
font:SetText(string.sub(tostring(secforstep * i), 1, 3))
end
local tex = f:CreateTexture(nil, "BACKGROUND")
tex:SetTexture(texture or default.texture)
 
tex:SetHeight(2)
tex:SetWidth(6)
tex:SetVertexColor(1, 1, 1, 1)
if not loflag then
tex:SetPoint("BOTTOMRIGHT", -16, part*i - 2)
if scaleinfo.scaletext then
font:SetPoint("BOTTOMRIGHT", 1, part*i)
end
else
tex:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 16, part*i - 2)
if scaleinfo.scaletext then
font:SetPoint("BOTTOMLEFT", 1, part*i)
end
end
end
if checkLog() then
scaleinfo.part = part
local count = steps + 1
local tex = maxtime
f:SetHeight(f:GetHeight() + part * #scaleinfo.amaxtimes)
for k,v in pairs(scaleinfo.amaxtimes) do
local font
if scaleinfo.scaletext then
font = f:CreateFontString()
setFont(font, "scale")
tex = tex + v
font:SetText(tex)
end
local tex = f:CreateTexture(nil, "BACKGROUND")
tex:SetTexture(texture or default.texture)
tex:SetWidth(6)
tex:SetHeight(2)
tex:SetVertexColor(1, 1, 1, 1)
 
if not loflag then
tex:SetPoint("BOTTOMRIGHT", -16, part*count - 2)
if scaleinfo.scaletext then
font:SetPoint("BOTTOMRIGHT", 1, part*count)
end
else
tex:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 16, part*count - 2)
if scaleinfo.scaletext then
font:SetPoint("BOTTOMLEFT", 1, part*count)
end
end
 
count = count + 1
end
end
maintexture:SetHeight(f:GetHeight())
return f
end
 
local function createHorizontalScale(width, maxtime, steps, handler, loflag, texture)
local secforstep = maxtime / steps
 
local f = CreateFrame("Frame", "SBarAnchorFrame",UIParent) -- only used for the scale
f:EnableMouse(true)
f:SetMovable(true)
f:SetFrameStrata("BACKGROUND")
f:SetWidth(width)
f:SetHeight(32)
f:SetPoint("CENTER",UIParent,"CENTER",0,0)
f:Show()
local function OnDragStart(self)
if not scaleinfo.locked then
if( IsAltKeyDown() ) then
self.isMoving = true
self:StartMoving()
end
end
end
local function OnDragStop(self)
if( self.isMoving) then
self:StopMovingOrSizing()
end
if type(handler) == "function" then
handler()
else
if handler then
local x, y = getPosition(scaleinfo.frame)
handler.x = x
handler.y = y
end
end
end
 
f:SetScript("OnMouseDown", OnDragStart)
f:SetScript("OnMouseUp", OnDragStop)
local maintexture = f:CreateTexture(nil, "BACKGROUND")
maintexture:SetTexture(texture or default.texture)
maintexture:SetPoint("CENTER", 0, -1)
maintexture:SetHeight(2)
maintexture:SetVertexColor(1, 1, 1, 1)
local part = f:GetWidth() / steps
for i = 0, steps do
local font
if scaleinfo.scaletext then
font = f:CreateFontString()
setFont(font, "scale")
font:SetText(string.sub(tostring(secforstep * i), 1, 3))
end
local tex = f:CreateTexture(nil, "BACKGROUND")
tex:SetTexture(texture or default.texture)
tex:SetHeight(6)
tex:SetWidth(2)
tex:SetVertexColor(1, 1, 1, 1)
if not loflag then
if i == steps then
tex:SetPoint("BOTTOMLEFT", width -2, 16)
else
tex:SetPoint("BOTTOMLEFT", part*i, 16)
end
if scaleinfo.scaletext then
font:SetPoint("BOTTOMLEFT", part*i, 0)
end
else
if i == steps then
tex:SetPoint("TOPLEFT", width - 2, -16)
else
tex:SetPoint("TOPLEFT", part*i - 2, -16)
end
if scaleinfo.scaletext then
font:SetPoint("TOPLEFT", f, "TOPLEFT", part*i, 0)
end
end
end
 
if checkLog() then
scaleinfo.part = part
local count = steps + 1
local tex = maxtime
f:SetWidth(f:GetWidth() + part * #scaleinfo.amaxtimes)
for k,v in pairs(scaleinfo.amaxtimes) do
local font
if scaleinfo.scaletext then
font = f:CreateFontString()
setFont(font, "scale")
tex = tex + v
font:SetText(tex)
end
local tex = f:CreateTexture(nil, "BACKGROUND")
tex:SetTexture(texture or default.texture)
tex:SetHeight(6)
tex:SetWidth(2)
tex:SetVertexColor(1, 1, 1, 1)
if not loflag then
tex:SetPoint("BOTTOMLEFT", part * count, 16)
if scaleinfo.scaletext then
font:SetPoint("BOTTOMLEFT", part * count, 0)
end
else
tex:SetPoint("TOPLEFT", part * count - 2, -16)
if scaleinfo.scaletext then
font:SetPoint("TOPLEFT", f, "TOPLEFT", part * count, 0)
end
end
count = count + 1
end
end
maintexture:SetWidth(f:GetWidth())
return f
end
local function createVerticalBar(data, duration, start, barheight, maxtime, text, icon, pos, color, colorzero, maxneg, loflag, texture)
local tmptime
if not scaleinfo.frame:IsShown() then
scaleinfo.frame:Show()
end
if not scaleinfo.frame:GetScript("OnUpdate") then
scaleinfo.frame:SetScript("OnUpdate", OnUpdate)
end
if not bars then bars = newList() end
if maxneg > start then
if checkLog() and (duration + start) > maxtime then
tmptime = duration
duration = maxtime
else
duration = duration + (start - maxneg)
end
start = maxneg
elseif checkLog() and (duration + start) > maxtime then
tmptime = duration
duration = maxtime
end
local sekinp = barheight / maxtime
-- barframe
local barf = CreateFrame("Frame", nil, scaleinfo.frame)
-- set it depending on the scale (right or left from the scale)
if not loflag then
barf:SetPoint("BOTTOMRIGHT", scaleinfo.frame, "BOTTOMLEFT", 8 - pos * scaleinfo.height, sekinp*start)
else
barf:SetPoint("BOTTOMLEFT", scaleinfo.frame, "BOTTOMRIGHT", -8 + pos * scaleinfo.height, sekinp*start)
end
barf:SetWidth(scaleinfo.height)
barf:SetHeight(sekinp*duration)
 
local barfon = newList()
--barfont
if text then
local count = 0
for ch in string.gmatch(string.upper(text), ".") do
-- first element
local fobj = barf:CreateFontString()
setFont(font)
barfon[count] = fobj
fobj:SetText(ch)
if count == 0 then
fobj:SetPoint("TOPLEFT", barf, "TOPLEFT", barf:GetWidth()/2 - fobj:GetStringWidth()/2 , -1*scaleinfo.height - 5)
else
fobj:SetPoint("TOPLEFT", barfon[count-1], "BOTTOMLEFT", 0, 0)
end
count = count + 1
end
end
 
--normal texture
local bart = barf:CreateTexture(nil, "BACKGROUND")
bart:SetTexture(texture or default.texture)
bart:SetPoint("TOPRIGHT", barf, "TOPRIGHT", 0, 0)
bart:SetWidth(barf:GetWidth())
bart:SetVertexColor(color.r, color.g, color.b, color.a)
 
-- grayed texture
local bartg = barf:CreateTexture(nil, "BACKGROUND")
bartg:SetTexture(texture or default.texture)
bartg:SetPoint("BOTTOMLEFT", barf, "BOTTOMLEFT", 0, 0)
bartg:SetWidth(barf:GetWidth())
bartg:SetVertexColor(colorzero.r, colorzero.g , colorzero.b, colorzero.a)
 
if(start < 0) then
if(math.abs(start) < duration) then
bart:Show()
bartg:Show()
bart:SetHeight(sekinp*(duration-math.abs(start)))
bartg:SetHeight(sekinp*math.abs(start))
else
bart:Hide()
bartg:Show()
bartg:SetHeight(barf:GetHeight())
end
else
bart:Show()
bartg:Hide()
bart:SetHeight(sekinp*duration)
end
-- create the logarithmic parts
if tmptime and checkLog() then
local count = 0
local mtime = maxtime
local parttime
for k, v in pairs(scaleinfo.amaxtimes) do
mtime = mtime + v
parttime = v
if mtime > tmptime then break end
count = count + 1
end
-- we have count full bars and count + 1 is the bar that is not full
local partsekinp = scaleinfo.part / parttime
local timeinseg = tmptime - (mtime - parttime)
barf:SetHeight(barf:GetHeight() + scaleinfo.part * count + partsekinp * timeinseg)
bart:SetHeight(bart:GetHeight() + scaleinfo.part * count + partsekinp * timeinseg)
duration = tmptime
end
tmptime = nil
-- icon
local baric = barf:CreateTexture(nil, "BORDER")
baric:SetTexture(icon)
baric:SetHeight(scaleinfo.height)
baric:SetWidth(scaleinfo.height)
if scaleinfo.iconpos then
baric:SetPoint("TOPRIGHT", barf, "TOPRIGHT", 0, baric:GetHeight())
else
baric:SetPoint("TOPRIGHT", barf, "TOPRIGHT", 0, 0)
end
tinsert(bars, { data = data, frame = barf, tex = bart, texg = bartg, dur = duration, start = start, pos = pos, text = barfon, icon = baric } )
end
--
local function createHorizontalBar(data, duration, start, barwidth, maxtime, text, icon, pos, color, colorzero, maxneg, loflag, texture)
--
local tmptime
if not scaleinfo.frame:IsShown() then
scaleinfo.frame:Show()
end
--
if not scaleinfo.frame:GetScript("OnUpdate") then
scaleinfo.frame:SetScript("OnUpdate", OnUpdate)
end
if not bars then bars = newList() end
if maxneg > start then
if checkLog() and (duration + start) > maxtime then
tmptime = duration
duration = maxtime
else
duration = duration + (start - maxneg)
end
start = maxneg
 
elseif checkLog() and (duration + start) > maxtime then
tmptime = duration
duration = maxtime
end
local sekinp = barwidth / maxtime
-- barframe
local barf = CreateFrame("Frame", nil, scaleinfo.frame)
if not loflag then
barf:SetPoint("BOTTOMLEFT", scaleinfo.frame, "TOPLEFT", sekinp*start, -8 + pos * scaleinfo.height)
else
barf:SetPoint("TOPLEFT", scaleinfo.frame, "BOTTOMLEFT", sekinp*start, 8 - pos * scaleinfo.height)
end
barf:SetWidth(sekinp*duration)
barf:SetHeight(scaleinfo.height)
 
-- barfont
local barfon = barf:CreateFontString()
setFont(barfon)
barfon:SetText(text)
barfon:SetPoint("BOTTOMRIGHT", barf, "BOTTOMRIGHT", -1 * scaleinfo.height - 5 , scaleinfo.height/2 - barfon:GetStringWidth()/2)
-- normal texture
local bart = barf:CreateTexture(nil, "BACKGROUND")
bart:SetTexture(texture or default.texture)
bart:SetPoint("TOPRIGHT", barf, "TOPRIGHT", 0, 0)
bart:SetHeight(barf:GetHeight())
bart:SetVertexColor(color.r, color.g, color.b, color.a)
 
-- grayed texture
local bartg = barf:CreateTexture(nil, "BACKGROUND")
bartg:SetTexture(texture or default.texture)
bartg:SetPoint("TOPLEFT", barf, "TOPLEFT", 0, 0)
bartg:SetHeight(barf:GetHeight())
bartg:SetVertexColor(colorzero.r, colorzero.g , colorzero.b, colorzero.a)
 
if(start < 0) then
if(math.abs(start) < duration) then
bart:Show()
bartg:Show()
bart:SetWidth(sekinp * (duration-math.abs(start)))
bartg:SetWidth(sekinp * math.abs(start))
else
bart:Hide()
bartg:Show()
bartg:SetWidth(barf:GetWidth())
end
else
bart:Show()
bartg:Hide()
bart:SetWidth(sekinp*duration)
end
-- create the logarithmic parts
if tmptime and checkLog() then
local count = 0
local mtime = maxtime
local parttime
for k, v in pairs(scaleinfo.amaxtimes) do
mtime = mtime + v
parttime = v
if mtime > tmptime then break end
count = count + 1
end
-- we have count full bars and count + 1 is the bar that is not full
local partsekinp = scaleinfo.part / parttime
local timeinseg = tmptime - (mtime - parttime)
barf:SetWidth(barf:GetWidth() + scaleinfo.part * count + partsekinp * timeinseg)
bart:SetWidth(bart:GetWidth() + scaleinfo.part * count + partsekinp * timeinseg)
duration = tmptime
end
tmptime = nil
-- icon
local baric = barf:CreateTexture(nil, "BORDER")
baric:SetTexture(icon)
baric:SetHeight(scaleinfo.height)
baric:SetWidth(scaleinfo.height)
if scaleinfo.iconpos then
baric:SetPoint("TOPRIGHT", barf, "TOPRIGHT", baric:GetWidth(), 0)
else
baric:SetPoint("TOPRIGHT", barf, "TOPRIGHT", 0, 0)
end
tinsert(bars, { data = data, frame = barf, tex = bart, texg = bartg, dur = duration, start = start, pos = pos, text = barfon, icon = baric } )
end
 
 
local function getMaxPos()
local maxpos = 0
if not bars then return false end
for _, bar in pairs(bars) do
if bar.pos and maxpos < bar.pos then
maxpos = bar.pos
end
end
return maxpos
end
 
 
 
local function updateFrameLevel()
if not getMaxPos() then return end
for i = 0, getMaxPos() do
local bartou = newList()
for _, bar in pairs(bars) do
if bar.pos == i then
tinsert(bartou, bar)
end
end
updateBarsFrameLevel(bartou)
end
end
 
function sbar:UpdateFrameLevel()
updateFrameLevel()
end
 
 
 
--*-------------------------------------------
-- public methods
--*-------------------------------------------
 
 
--- Returns recycling functions which are used to create, delete and copy tables
-- @return newList Creates a new table. Example: table = newList()
-- @return del Deletes a table. Example: del(table)
-- @return deepDel Deletes the table and every nested table. Example: deepDel(table)
-- @return deepCopy Creates a copy of the table (includes nested tables). Example: table2 = deepCopy(table)
 
function sbar:GetRecyclingFunctions() return newList, del, deepDel, deepCopy end
--- Sets the text of a bar
-- @param bar The bar of which the text should be set.
-- @param text The text that will be used.
function sbar:SetText(bar, text)
argcheck(bar, 1, "table")
argcheck(text, 2, "string")
if scaleinfo.horizontal then
bar.text:SetText(text)
else
local count = 0
--if not bar.text then bar.text = newList() end
for _, te in pairs(bar.text) do
te:SetText()
te = nil
end
for ch in string.gmatch(string.reverse(string.upper(text)), ".") do
-- first element
local fobj = bar.text[count]
if not fobj then
fobj = bar.frame:CreateFontString()
setFont(fobj)
bar.text[count] = fobj
end
fobj:SetText(ch)
if count == 0 then
fobj:SetPoint("BOTTOMLEFT", bar.frame, "BOTTOMLEFT", 0 , 5)
else
fobj:SetPoint("BOTTOMLEFT", bar.text[count-1], "TOPLEFT", 0, 0)
end
count = count + 1
end
end
end
--- Gets the text of a bar
-- @param bar The bar of which the text should be returned.
-- @return The text of the bar
function sbar:GetText(bar)
argcheck(bar, 1, "table")
if scaleinfo.horizontal then
return bar.text:GetText(text)
else
if bar.text then
local rstr = ""
for i = 0, #bar.text do
if bar.text[i] and bar.text[i]:GetText() then
rstr = rstr .. bar.text[i]:GetText()
end
end
return string.reverse(rstr)
end
end
end
--- Creates a bar on the previously created scale
-- @param data User specific data.
-- @param duration Current duration in seconds.
-- @param start Current start time in seconds.
-- @param text FontString object.
-- @param icon Path to an icon (or any other texture).
-- @param pos The current position of the bar (horizontal = y, vertical = x).
-- @param color The color for the positive side of the bar (color_def).
-- @param colorzero The color for the negative side of the bar (color_def).
-- @see color_def
function sbar:CreateBar(data, duration, start, text, icon, pos, color, colorzero, texture)
argcheck(duration, 2, "number")
argcheck(start, 3, "number")
argcheck(text, 4, "string", "nil")
argcheck(icon, 5, "string", "nil")
argcheck(pos, 6, "number")
argcheck(color, 7, "table")
argcheck(colorzero, 8, "table")
argcheck(texture, 9, "string", "nil")
local scale
if scaleinfo.horizontal then
createHorizontalBar(data, duration, start, scaleinfo.size, scaleinfo.maxtime, text, icon, pos, color, colorzero, scaleinfo.maxneg, scaleinfo.loflag, texture)
else
createVerticalBar(data, duration, start, scaleinfo.size, scaleinfo.maxtime, text, icon, pos, color, colorzero, scaleinfo.maxneg, scaleinfo.loflag, texture)
end
self:UpdateFrameLevel()
end
function sbar:SetIcon(iconpos)
scaleinfo.iconpos = iconpos
end
--- Creates the scale for the bar
-- @name CreateScale
-- @param size The size of the scale. If the bar is horizontal then this parameter describes the x value otherwise the y.
-- @param maxtime The maximum time which can be displayed on the scale
-- @param steps This paramter describes how many markers you will have on the bar (execluding the zero).
-- If you want to create a bar which should display 10 seconds and you want to have a sperator every second then this
-- parameter will be ten.
-- @param maxneg Optional parameter that describes if the bar should truncate somewhere. If you have a 30 second long bar and
-- want it to start resizing when it has reached -10 then this paramter should be -10.
-- @param horizontal Optional parameter that describes if the bar should be horizontal. Default is vertical.
-- @param savepos Function which is called when the frame dragging is stoped or a table which is filled with x and y values.
-- @param loflag Indicates if the scale is on the left or above the bars (default is right or beneath)
-- @param texture The texture of the scale
-- @param locked The lock status of the bar
function sbar:CreateScale(size, maxtime, steps, maxneg, savepos, horizontal, loflag, texture, locked, scale, height, fonts, scaletext, amaxtimes, hide, iconpos)
argcheck(size, 1, "number")
argcheck(maxtime, 2, "number")
argcheck(steps, 3, "number")
argcheck(maxneg, 4, "number")
argcheck(savepos, 5, "function", "table", "nil")
argcheck(horizontal, 6, "boolean", "nil")
argcheck(loflag, 7, "boolean", "nil")
argcheck(texture, 8, "string", "nil")
argcheck(locked, 9, "boolean", "nil")
argcheck(scale, 10, "number")
argcheck(height, 11, "number")
argcheck(fonts, 12, "table")
argcheck(scaletext, 13, "boolean", "nil")
argcheck(amaxtimes, 14, "table")
argcheck(hide, 15, "boolean", "nil")
argcheck(iconpos, 16, "boolean", "nil")
scaleinfo = newList()
scaleinfo.fonts = deepCopy(fonts)
scaleinfo.scaletext = scaletext
scaleinfo.amaxtimes = deepCopy(amaxtimes)
scaleinfo.iconpos = iconpos
scaleinfo.hide = hide
if horizontal then
scaleinfo.frame = createHorizontalScale(size, maxtime, steps, savepos, loflag, texture)
else
scaleinfo.frame = createVericalScale(size, maxtime, steps, savepos, loflag, texture)
end
scaleinfo.frame:SetScale(scale)
scaleinfo.horizontal = horizontal
scaleinfo.size = size
scaleinfo.maxtime = maxtime
scaleinfo.maxneg = maxneg
scaleinfo.loflag = loflag
scaleinfo.locked = locked
scaleinfo.height = height
 
if type(savepos) == "table" and savepos.x and savepos.y then
sbar:SetPosition(savepos.x, savepos.y)
end
scaleinfo.frame:SetScript("OnUpdate", OnUpdate)
end
function sbar:SetScale(scale)
scaleinfo.frame:SetScale(scale)
end
function sbar:GetScale()
return scale
end
 
function sbar:SetLock(status)
scaleinfo.locked = status
end
--- Gets the Position of the main frame (the scale)
-- @return x The x value.
-- @return y The y value.
function sbar:GetPosition()
return getPosition(scaleinfo.frame)
end
--- Sets the Position of the main frame (the scale)
-- @param x The x value.
-- @param y The y value.
function sbar:SetPosition(x, y)
argcheck(x, 1, "number")
argcheck(y, 2, "number")
setPosition(scaleinfo.frame, x, y)
end
--- Finds (a) bar(s) depending on the parameters
-- @param duration The current duration of a barf
-- @param start The current start values
-- @param text The text of the bar
-- @param icon The icon of the bar
-- @param pos The position on the barf
-- @return A table with bars (bars_def)
-- @see bars_def
function sbar:FindBars(duration, start, text, icon, pos)
argcheck(duration, 1, "number", "nil")
argcheck(start, 2, "number", "nil")
argcheck(text, 3, "text", "nil")
argcheck(icon, 4, "text", "nil")
argcheck(pos, 5, "number", "nil")
 
local barfind
if not(duration and start and text and icon and pos) then
return deepCopy(bars)
end
for _, bar in pairs(bars) do
if bar.pos then
local inp = newList(duration, start, text, icon, pos)
local outer = newList(bar.dur, bar.start, bar.text, bar.icon, bar.pos)
local check = true
for i = 1, 5 do
if (inp[i] and not outer[i]) or (inp[i] ~= outer[i]) then
check = false
end
end
if check then
if not barfind then barfind = newList() end
tinsert(barfind, deepCopy(bar))
end
end
end
return barfind
end
--- This function sets a text at the end of the bar.
-- So it will always be at the maxneg position
-- @param text The text for the bar
-- @param pos The position on the bar
 
function sbar:SetFixedText(text, pos)
argcheck(text, 1, "string", "nil")
argcheck(pos, 2, "number")
 
local sekinp = scaleinfo.size / scaleinfo.maxtime
 
if scaleinfo.horizontal then
if fixedText[pos] then
fixedText[pos]:SetText()
fixedText[pos]:Hide()
fixedText[pos] = nil
end
if not text then return end
local fobj
 
fobj = scaleinfo.frame:CreateFontString()
setFont(fobj)
fobj:SetText(text)
if not scaleinfo.loflag then
fobj:SetPoint("BOTTOMRIGHT", scaleinfo.frame, "TOPLEFT", sekinp*scaleinfo.maxneg, -8 + pos * scaleinfo.height + scaleinfo.height/2 - fobj:GetStringHeight()/2)
else
fobj:SetPoint("TOPRIGHT", scaleinfo.frame, "BOTTOMLEFT", sekinp*scaleinfo.maxneg, 8 - pos * scaleinfo.height - scaleinfo.height/2 + fobj:GetStringHeight()/2)
end
fixedText[pos] = fobj
else
local count = 0
if not fixedText[pos] then fixedText[pos] = newList() end
for _, te in pairs(fixedText[pos]) do
te:SetText()
te:Hide()
te = nil
end
if not text then return end
text = string.sub(string.upper(text), 1, 10)
for ch in string.gmatch(text, ".") do
-- first element
local fobj = fixedText[pos][count]
if not fobj then
fobj = scaleinfo.frame:CreateFontString()
setFont(fobj)
fixedText[pos][count] = fobj
end
fobj:SetText(ch)
fobj:Show()
if count == 0 then
if not scaleinfo.loflag then
fobj:SetPoint("TOPRIGHT", scaleinfo.frame, "BOTTOMLEFT", 8 - pos*scaleinfo.height - scaleinfo.height/2 + fobj:GetStringHeight()/2, sekinp*scaleinfo.maxneg)
else
fobj:SetPoint("TOPLEFT", scaleinfo.frame, "BOTTOMRIGHT", -8 + pos * scaleinfo.height + scaleinfo.height/2 - fobj:GetStringHeight()/2, sekinp*scaleinfo.maxneg)
end
else
fobj:SetPoint("TOPLEFT", fixedText[pos][count-1], "BOTTOMLEFT", 0, 0)
end
count = count + 1
end
end
end
--- Returns a table with all the bars
-- @return bars
-- @see bars_def
function sbar:GetBars()
return bars
end
--- Redraws the Scale
-- @see CreateScale
function sbar:RedrawScale(size, maxtime, steps, maxneg, savepos, horizontal, loflag, texture, locked, scale, height, fonts, scaletext, amaxtimes, hide, iconpos)
if bars then
for _, bar in pairs(bars) do
if bar.frame then
if bar.frame:IsShown() then
for _, child in pairs(bar.frame:GetChildren() or {}) do
child:Hide()
end
bar.frame:Hide()
bar = nil
end
end
end
end
if scaleinfo and scaleinfo.frame then
--for _, child in pairs(scaleinfo.frame:GetChildren()) do
-- child:Hide()
--end
scaleinfo.frame:Hide()
scaleinfo.frame:SetScript("OnUpdate",nil)
deepDel(scaleinfo)
end
deepDel(fixedText)
fixedText = nil
fixedText = newList()
sbar:CreateScale(size, maxtime, steps, maxneg, savepos, horizontal, loflag, texture, locked, scale, height, fonts, scaletext, amaxtimes, hide, iconpos)
end
--*--------------------------------
-- only for documentation purpose
--*--------------------------------
--- Table that holds the information for the bars
-- @class table
-- @name bars_def
-- @field data Can be assigned with anything from the user.
-- @field frame The frame of the bar.
-- @field tex The texture which belongs to the positive area.
-- @field texg The texture which belong to the negative area.
-- @field dur The current duration of the bar.
-- @field start The current start time of the bar.
-- @field pos The position of the bar (horizontal = x position, vertical = y position).
-- @field text The text item which will be displayed only if the bar is horizontal.
-- @field icon The icon of the bar.
local bars_def = { data = data, frame = frame, tex = tex, texg = texg, dur = dur, start = start, pos = pos, text = text, icon = icon }
bars_def = nil
--- A Table that holds color information
-- @class table
-- @name color_def
-- @field r Red (0.0 - 1.0).
-- @field g Green (0.0 - 1.0).
-- @field b Blue (0.0 - 1.0).
-- @field a Alpha (0.0 - 1.0).
local color_def = { r = r, g = g, b = b, a = a }
color = nil