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 |