Files
2023-09-27 20:37:32 +03:00

2949 lines
85 KiB
Lua

--[[
Name: Tablet-2.0
Revision: $Rev: 23368 $
Author(s): ckknight (ckknight@gmail.com)
Website: http://ckknight.wowinterface.com/
Documentation: http://www.wowace.com/index.php/Tablet-2.0
SVN: http://svn.wowace.com/wowace/trunk/TabletLib/Tablet-2.0
Description: A library to provide an efficient, featureful tooltip-style display.
Dependencies: AceLibrary, (optional) Dewdrop-2.0
License: LGPL v2.1
]]
local MAJOR_VERSION = "Tablet-2.0"
local MINOR_VERSION = "$Revision: 23368 $"
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
local DEBUG = false
local SCROLL_UP = "Scroll up"
local SCROLL_DOWN = "Scroll down"
local HINT = "Hint"
local DETACH = "Detach"
local DETACH_DESC = "Detach the tablet from its source."
local SIZE = "Size"
local SIZE_DESC = "Scale the tablet."
local CLOSE_MENU = "Close menu"
local CLOSE_MENU_DESC = "Close the menu."
local COLOR = "Background color"
local COLOR_DESC = "Set the background color."
local LOCK = "Lock"
local LOCK_DESC = "Lock the tablet in its current position. Alt+Right-click for menu or Alt+drag to drag it when locked."
if GetLocale() == "deDE" then
SCROLL_UP = "Hochscrollen"
SCROLL_DOWN = "Runterscrollen"
HINT = "Hinweis"
DETACH = "L\195\182sen"
DETACH_DESC = "L\195\182st den Tooltip aus seiner Verankerung."
SIZE = "Gr\195\182\195\159e"
SIZE_DESC = "Gr\195\182\195\159e des Tooltips \195\164ndern."
CLOSE_MENU = "Menu schlie\195\159en"
CLOSE_MENU_DESC = "Schlie\195\159t das Menu."
COLOR = "Hintergrundfarbe"
COLOR_DESC = "Hintergrundfarbe setzen."
LOCK = "Sperren"
LOCK_DESC = "Sperrt die aktuelle Position vom Tooltip. Alt+Rechts-klick f\195\188rs Men\195\188 oder Alt+Verschieben f\195\188rs verschieben wenn es gesperrt ist."
elseif GetLocale() == "koKR" then
SCROLL_UP = "위로 스크롤"
SCROLL_DOWN = "아래로 스크롤"
HINT = "힌트"
DETACH = "분리"
DETACH_DESC = "테이블을 분리합니다."
SIZE = "크기"
SIZE_DESC = "테이블의 크기입니다."
CLOSE_MENU = "메뉴 닫기"
CLOSE_MENU_DESC = "메뉴를 닫습니다."
COLOR = "배경 색상"
COLOR_DESC = "배경 색상을 설정합니다."
LOCK = "고정"
LOCK_DESC = "현재 위치에 테이블을 고정합니다. 알트+우클릭 : 메뉴열기, 알트+드래그 : 고정된것을 드래그합니다."
elseif GetLocale() == "zhCN" then
SCROLL_UP = "向上翻转"
SCROLL_DOWN = "向上翻转"
HINT = "提示"
DETACH = "分离"
DETACH_DESC = "分离菜单为独立提示."
SIZE = "尺寸"
SIZE_DESC = "缩放菜单显示尺寸."
CLOSE_MENU = "关闭菜单"
CLOSE_MENU_DESC = "关闭菜单"
COLOR = "背景颜色"
COLOR_DESC = "设置菜单背景颜色."
LOCK = "锁定"
LOCK_DESC = "锁定菜单当前位置. alt+右键 将显示选项, alt+拖动 可以移动已锁定的菜单."
elseif GetLocale() == "zhTW" then
SCROLL_UP = "向上翻轉"
SCROLL_DOWN = "向上翻轉"
HINT = "提示"
DETACH = "分離"
DETACH_DESC = "分離選單為獨立提示。"
SIZE = "尺寸"
SIZE_DESC = "縮放選單顯示尺寸。"
CLOSE_MENU = "關閉選單"
CLOSE_MENU_DESC = "關閉選單"
COLOR = "背景顏色"
COLOR_DESC = "設置選單背景顏色。"
LOCK = "鎖定"
LOCK_DESC = "鎖定選單目前位置. Alt+右鍵 將顯示選項,Alt+拖動 可以移動已鎖定的選單。"
elseif GetLocale() == "frFR" then
SCROLL_UP = "Parcourir vers le haut"
SCROLL_DOWN = "Parcourir vers le bas"
HINT = "Astuce"
DETACH = "D\195\169tacher"
DETACH_DESC = "Permet de d\195\169tacher le tableau de sa source."
SIZE = "Taille"
SIZE_DESC = "Permet de changer l'\195\169chelle du tableau."
CLOSE_MENU = "Fermer le menu"
CLOSE_MENU_DESC = "Ferme ce menu."
COLOR = "Couleur du fond"
COLOR_DESC = "Permet de d\195\169finir la couleur du fond."
LOCK = "Bloquer"
LOCK_DESC = "Bloque le tableau \195\160 sa position actuelle. Alt+clic-droit pour le menu ou Alt+glisser pour le d\195\169placer quand il est bloqu\195\169."
elseif GetLocale() == "esES" then
SCROLL_UP = "Desplazar hacia arriba"
SCROLL_DOWN = "Desplazar hacia abajo"
HINT = "Consejo"
DETACH = "Separar"
DETACH_DESC = "Separa el tooltip de su fuente."
SIZE = "Tama\195\177o"
SIZE_DESC = "Escala el tooltip"
CLOSE_MENU = "Cerrar men\195\186"
CLOSE_MENU_DESC = "Cierra el men\195\186"
COLOR = "Color de fondo"
COLOR_DESC = "Establece el color de fondo"
LOCK = "Bloquear"
LOCK_DESC = "Bloquea el tooltip en su posici\195\179n actual. Clic+Alt para el men\195\186 y arrastra+Alt para arrastrarlo cuando est\195\161 bloqueado"
end
local start = GetTime()
local wrap
local GetProfileInfo
if DEBUG then
local tree = {}
local treeMemories = {}
local treeTimes = {}
local memories = {}
local times = {}
function wrap(value, name)
if type(value) == "function" then
local oldFunction = value
memories[name] = 0
times[name] = 0
return function(self, ...)
local pos = #tree
table.insert(tree, name)
table.insert(treeMemories, 0)
table.insert(treeTimes, 0)
local t, mem = GetTime(), gcinfo()
local r1, r2, r3, r4, r5, r6, r7, r8 = oldFunction(self, ...)
mem, t = gcinfo() - mem, GetTime() - t
if pos > 0 then
treeMemories[pos] = treeMemories[pos] + mem
treeTimes[pos] = treeTimes[pos] + t
end
local otherMem = table.remove(treeMemories)
if mem - otherMem > 0 then
memories[name] = memories[name] + mem - otherMem
end
times[name] = times[name] + t - table.remove(treeTimes)
table.remove(tree)
return r1, r2, r3, r4, r5, r6, r7, r8
end
end
end
function GetProfileInfo()
return GetTime() - start, times, memories
end
else
function wrap(value)
return value
end
end
local MIN_TOOLTIP_SIZE = 200
local TESTSTRING_EXTRA_WIDTH = 8
local Tablet = {}
local Dewdrop = nil
local CleanCategoryPool
local pool = {}
local function del(t)
if t then
for k in pairs(t) do
t[k] = nil
end
setmetatable(t, nil)
pool[t] = true
end
end
local new
local function copy(parent)
local t = next(pool) or {}
pool[t] = nil
if parent then
for k,v in pairs(parent) do
t[k] = v
end
setmetatable(t, getmetatable(parent))
end
return t
end
function new(...)
local t = next(pool) or {}
pool[t] = nil
for i = 1, select('#', ...), 2 do
local k = select(i, ...)
if k then
t[k] = select(i+1, ...)
else
break
end
end
return t
end
local tmp
tmp = setmetatable({}, {__index = function(self, key)
local t = {}
tmp[key] = function(...)
for k in pairs(t) do
t[k] = nil
end
for i = 1, select('#', ...), 2 do
local k = select(i, ...)
if k then
t[k] = select(i+1, ...)
else
break
end
end
return t
end
return tmp[key]
end})
local headerSize, normalSize
if GameTooltipHeaderText then
_,headerSize = GameTooltipHeaderText:GetFont()
else
headerSize = 14
end
if GameTooltipText then
_,normalSize = GameTooltipText:GetFont()
else
normalSize = 12
end
local tooltip
local testString-- = CreateFrame("Frame", UIParent):CreateFontString(nil, "OVERLAY")
local TabletData = {}
local Category = {}
local Line = {}
local function getTestWidth(font, size, text)
testString:SetWidth(0)
testString:SetFontObject(font)
local a,_,b = testString:GetFont()
testString:SetFont(a, size, b)
testString:SetText(text)
return testString:GetStringWidth()-- + TESTSTRING_EXTRA_WIDTH
end
do
local TabletData_mt = { __index = TabletData }
function TabletData:new(tablet)
local self = new()
self.categories = new()
self.id = 0
self.width = 0 -- (MIN_TOOLTIP_SIZE - 20)*tablet.fontSizePercent
self.tablet = tablet
self.title = "Title"
self.titleR, self.titleG, self.titleB = nil, nil, nil
self.num_lines = 0
setmetatable(self, TabletData_mt)
return self
end
function TabletData:checkMinWidth()
local width = (MIN_TOOLTIP_SIZE - 20)*self.tablet.fontSizePercent
if self.width < width then
self.width = width
end
end
function TabletData:del()
for k, v in ipairs(self.categories) do
v:del()
end
del(self.categories)
del(self)
end
function TabletData:Display()
if self.tablet == tooltip or self.tablet.registration.showTitleWhenDetached then
local info = new(
'hideBlankLine', true,
'text', self.title,
'justify', "CENTER",
'font', GameTooltipHeaderText,
'isTitle', true
)
if self.titleR then
info.textR = self.titleR
info.textG = self.titleG
info.textB = self.titleB
end
self:AddCategory(info, 1)
del(info)
end
if self.tablet == tooltip or self.tablet.registration.showHintWhenDetached then
if self.hint then
self:AddCategory(nil):AddLine(
'text', HINT .. ": " .. self.hint,
'textR', 0,
'textG', 1,
'textB', 0,
'wrap', true
)
end
end
local tabletData = self.tabletData
for k, v in ipairs(self.categories) do
local width
if v.columns <= 2 then
width = v.x1
else
width = v.x1 + v.x2 + v.x3 + v.x4 + v.x5 + v.x6 + (v.columns - 1) * 20
end
if self.width < width then
self.width = width
end
end
local good = false
local lastTitle = true
for k, v in ipairs(self.categories) do
if lastTitle then
v.hideBlankLine = true
lastTitle = false
end
if v:Display(self.tablet) and (not v.isTitle or not self.tablet.registration.hideWhenEmpty or next(self.categories, k)) then
good = true
end
if v.isTitle then
lastTitle = true
end
end
if not good then
if self.tablet == tooltip or not self.tablet.registration.hideWhenEmpty then
local width
local info = new(
'hideBlankLine', true,
'text', self.title,
'justify', "CENTER",
'font', GameTooltipHeaderText,
'isTitle', true
)
local cat = self:AddCategory(info)
del(info)
self.width = self.categories[#self.categories].x1
cat:Display(self.tablet)
else
self.tablet:__Hide()
self.tablet.tmpHidden = true
end
else
self.tablet:__Show()
self.tablet.tmpHidden = nil
end
end
function TabletData:AddCategory(info, index)
local made = false
if not info then
made = true
info = new()
end
local cat = Category:new(self, info)
if index then
table.insert(self.categories, index, cat)
else
table.insert(self.categories, cat)
end
if made then
del(info)
end
return cat
end
function TabletData:SetHint(hint)
self.hint = hint
end
function TabletData:SetTitle(title)
self.title = title or "Title"
end
function TabletData:SetTitleColor(r, g, b)
self.titleR = r
self.titleG = g
self.titleB = b
end
end
do
local Category_mt = { __index = Category }
function Category:new(tabletData, info, superCategory)
local self = copy(info)
if superCategory and not self.noInherit then
self.superCategory = superCategory.superCategory
for k, v in pairs(superCategory) do
if string.find(k, "^child_") then
local k = strsub(k, 7)
if self[k] == nil then
self[k] = v
end
end
end
self.columns = superCategory.columns
else
self.superCategory = self
end
self.tabletData = tabletData
self.lines = new()
if not self.columns then
self.columns = 1
end
self.x1 = 0
self.x2 = 0
self.x3 = 0
self.x4 = 0
self.x5 = 0
self.x6 = 0
setmetatable(self, Category_mt)
self.lastWasTitle = nil
if self.text or self.text2 or self.text3 or self.text4 or self.text5 or self.text6 then
local x = new(
'category', category,
'text', self.text,
'textR', self.textR or 1,
'textG', self.textG or 1,
'textB', self.textB or 1,
'fakeChild', true,
'func', self.func,
'hasCheck', self.hasCheck,
'checked', self.checked,
'checkIcon', self.checkIcon,
'isRadio', self.isRadio,
'font', self.font,
'size', self.size,
'wrap', self.wrap,
'catStart', true,
'indentation', self.indentation,
'noInherit', true,
'justify', self.justify,
'justify2', self.justify2,
'justify3', self.justify3,
'justify4', self.justify4,
'justify5', self.justify5,
'justify6', self.justify6
)
local i = 1
while true do
local k = 'arg' .. i
local v = self[k]
if v == nil then
break
end
x[k] = v
i = i + 1
end
if self.isTitle then
x.textR = self.textR or 1
x.textG = self.textG or 0.823529
x.textB = self.textB or 0
else
x.textR = self.textR or 1
x.textG = self.textG or 1
x.textB = self.textB or 1
end
x.text2 = self.text2
x.text3 = self.text3
x.text4 = self.text4
x.text5 = self.text5
x.text6 = self.text6
x.text2R = self.text2R or self.textR2 or 1
x.text2G = self.text2G or self.textG2 or 1
x.text2B = self.text2B or self.textB2 or 1
x.text3R = self.text3R or self.textR3 or 1
x.text3G = self.text3G or self.textG3 or 1
x.text3B = self.text3B or self.textB3 or 1
x.text4R = self.text4R or self.textR4 or 1
x.text4G = self.text4G or self.textG4 or 1
x.text4B = self.text4B or self.textB4 or 1
x.text5R = self.text5R or self.textR5 or 1
x.text5G = self.text5G or self.textG5 or 1
x.text5B = self.text5B or self.textB5 or 1
x.text6R = self.text6R or self.textR6 or 1
x.text6G = self.text6G or self.textG6 or 1
x.text6B = self.text6B or self.textB6 or 1
x.font2 = self.font2
x.font3 = self.font3
x.font4 = self.font4
x.font5 = self.font5
x.font6 = self.font6
x.size2 = self.size2
x.size3 = self.size3
x.size4 = self.size4
x.size5 = self.size5
x.size6 = self.size6
self:AddLine(x)
del(x)
self.lastWasTitle = true
end
return self
end
function Category:del()
local prev = garbageLine
for k, v in pairs(self.lines) do
v:del()
end
del(self.lines)
del(self)
end
function Category:AddLine(...)
self.lastWasTitle = nil
local line
local k1 = ...
if type(k1) == "table" then
local k2 = select(2, ...)
Line:new(self, k1, k2)
else
local info = new(...)
Line:new(self, info)
info = del(info)
end
end
function Category:AddCategory(...)
local lastWasTitle = self.lastWasTitle
self.lastWasTitle = nil
local info
local k1 = ...
if type(k1) == "table" then
info = k1
else
info = new(...)
end
if lastWasTitle or #self.lines == 0 then
info.hideBlankLine = true
end
local cat = Category:new(self.tabletData, info, self)
table.insert(self.lines, cat)
if info ~= k1 then
info = del(info)
end
return cat
end
function Category:HasChildren()
local hasChildren = false
for k, v in ipairs(self.lines) do
if v.HasChildren then
if v:HasChildren() then
return true
end
end
if not v.fakeChild then
return true
end
end
return false
end
local lastWasTitle = false
function Category:Display(tablet)
if not self.isTitle and not self.showWithoutChildren and not self:HasChildren() then
return false
end
if not self.hideBlankLine and not lastWasTitle then
local info = new(
'blank', true,
'fakeChild', true
)
self:AddLine(info, 1)
del(info)
end
local good = false
if #self.lines > 0 then
self.tabletData.id = self.tabletData.id + 1
self.id = self.tabletData.id
for k, v in ipairs(self.lines) do
if v:Display(tablet) then
good = true
end
end
end
lastWasTitle = self.isTitle
return good
end
end
do
local Line_mt = { __index = Line }
function Line:new(category, info, position)
local self = copy(info)
if not info.noInherit then
for k, v in pairs(category) do
if string.find(k, "^child_") then
local k = strsub(k, 7)
if self[k] == nil then
self[k] = v
end
end
end
end
self.category = category
if position then
table.insert(category.lines, position, self)
else
table.insert(category.lines, self)
end
setmetatable(self, Line_mt)
local n = category.tabletData.num_lines + 1
category.tabletData.num_lines = n
if n == 15 then
category.tabletData:checkMinWidth()
end
local columns = category.columns
if columns == 1 then
if not self.justify then
self.justify = "LEFT"
end
elseif columns == 2 then
self.justify = "LEFT"
self.justify2 = "RIGHT"
if self.wrap then
self.wrap2 = false
end
elseif columns == 3 then
if not self.justify then
self.justify = "LEFT"
end
if not self.justify2 then
self.justify2 = "CENTER"
end
if not self.justify3 then
self.justify3 = "RIGHT"
end
if self.wrap then
self.wrap2 = false
self.wrap3 = false
elseif self.wrap2 then
self.wrap3 = false
end
elseif columns == 4 then
if not self.justify then
self.justify = "LEFT"
end
if not self.justify2 then
self.justify2 = "CENTER"
end
if not self.justify3 then
self.justify3 = "CENTER"
end
if not self.justify4 then
self.justify4 = "RIGHT"
end
if self.wrap then
self.wrap2 = false
self.wrap3 = false
self.wrap4 = false
elseif self.wrap2 then
self.wrap3 = false
self.wrap4 = false
elseif self.wrap3 then
self.wrap4 = false
end
elseif columns == 5 then
if not self.justify then
self.justify = "LEFT"
end
if not self.justify2 then
self.justify2 = "CENTER"
end
if not self.justify3 then
self.justify3 = "CENTER"
end
if not self.justify4 then
self.justify4 = "CENTER"
end
if not self.justify5 then
self.justify5 = "RIGHT"
end
if self.wrap then
self.wrap2 = false
self.wrap3 = false
self.wrap4 = false
self.wrap5 = false
elseif self.wrap2 then
self.wrap3 = false
self.wrap4 = false
self.wrap5 = false
elseif self.wrap3 then
self.wrap4 = false
self.wrap5 = false
elseif self.wrap4 then
self.wrap5 = false
end
elseif columns == 6 then
if not self.justify then
self.justify = "LEFT"
end
if not self.justify2 then
self.justify2 = "CENTER"
end
if not self.justify3 then
self.justify3 = "CENTER"
end
if not self.justify4 then
self.justify4 = "CENTER"
end
if not self.justify5 then
self.justify5 = "CENTER"
end
if not self.justify6 then
self.justify6 = "RIGHT"
end
if self.wrap then
self.wrap2 = false
self.wrap3 = false
self.wrap4 = false
self.wrap5 = false
self.wrap6 = false
elseif self.wrap2 then
self.wrap3 = false
self.wrap4 = false
self.wrap5 = false
self.wrap6 = false
elseif self.wrap3 then
self.wrap4 = false
self.wrap5 = false
self.wrap6 = false
elseif self.wrap4 then
self.wrap5 = false
self.wrap6 = false
elseif self.wrap5 then
self.wrap6 = false
end
end
if self.textR2 then
self.text2R, self.textR2 = self.text2R or self.textR2
self.text2G, self.textG2 = self.text2G or self.textG2
self.text2B, self.textB2 = self.text2B or self.textB2
if self.textR3 then
self.text3R, self.textR3 = self.text3R or self.textR3
self.text3G, self.textG3 = self.text3G or self.textG3
self.text3B, self.textB3 = self.text3B or self.textB3
if self.textR4 then
self.text4R, self.textR4 = self.text4R or self.textR4
self.text4G, self.textG4 = self.text4G or self.textG4
self.text4B, self.textB4 = self.text4B or self.textB4
if self.textR5 then
self.text5R, self.textR5 = self.text5R or self.textR5
self.text5G, self.textG5 = self.text5G or self.textG5
self.text5B, self.textB5 = self.text5B or self.textB5
if self.textR5 then
self.text6R, self.textR6 = self.text6R or self.textR6
self.text6G, self.textG6 = self.text6G or self.textG6
self.text6B, self.textB6 = self.text6B or self.textB6
end
end
end
end
end
if not self.indentation or self.indentation < 0 then
self.indentation = 0
end
if not self.font then
self.font = GameTooltipText
end
if not self.font2 then
self.font2 = self.font
end
if not self.font3 then
self.font3 = self.font
end
if not self.font4 then
self.font4 = self.font
end
if not self.font5 then
self.font5 = self.font
end
if not self.font6 then
self.font6 = self.font
end
if not self.size then
_,self.size = self.font:GetFont()
end
if not self.size2 then
_,self.size2 = self.font2:GetFont()
end
if not self.size3 then
_,self.size3 = self.font3:GetFont()
end
if not self.size4 then
_,self.size4 = self.font4:GetFont()
end
if not self.size5 then
_,self.size5 = self.font5:GetFont()
end
if not self.size6 then
_,self.size6 = self.font6:GetFont()
end
local fontSizePercent = category.tabletData.tablet.fontSizePercent
local w = 0
self.checkWidth = 0
testString = category.tabletData.tablet.lefts[1]
if self.text then
if not self.wrap then
local testWidth = getTestWidth(self.font, self.size * fontSizePercent, self.text)
local checkWidth = self.hasCheck and self.size * fontSizePercent or 0
self.checkWidth = checkWidth
w = testWidth + self.indentation * fontSizePercent + checkWidth
if category.superCategory.x1 < w then
category.superCategory.x1 = w
end
else
if columns == 1 then
local testWidth = getTestWidth(self.font, self.size * fontSizePercent, self.text)
local checkWidth = self.hasCheck and self.size * fontSizePercent or 0
self.checkWidth = checkWidth
w = testWidth + self.indentation * fontSizePercent + checkWidth
if w > (MIN_TOOLTIP_SIZE - 20) * fontSizePercent then
w = (MIN_TOOLTIP_SIZE - 20) * fontSizePercent
end
else
w = MIN_TOOLTIP_SIZE * fontSizePercent / 2
end
if category.superCategory.x1 < w then
category.superCategory.x1 = w
end
end
end
if columns == 2 and self.text2 then
if not self.wrap2 then
local testWidth = getTestWidth(self.font2, self.size2 * fontSizePercent, self.text2)
w = w + 40 * fontSizePercent + testWidth
if category.superCategory.x1 < w then
category.superCategory.x1 = w
end
else
w = w + 40 * fontSizePercent + MIN_TOOLTIP_SIZE * fontSizePercent / 2
if category.superCategory.x1 < w then
category.superCategory.x1 = w
end
end
elseif columns >= 3 then
if self.text2 then
if not self.wrap2 then
local testWidth = getTestWidth(self.font2, self.size2 * fontSizePercent, self.text2)
local w = testWidth
if category.superCategory.x2 < w then
category.superCategory.x2 = w
end
else
local w = MIN_TOOLTIP_SIZE / 2
if category.superCategory.x2 < w then
category.superCategory.x2 = w
end
end
end
if self.text3 then
if not self.wrap3 then
local testWidth = getTestWidth(self.font3, self.size3 * fontSizePercent, self.text3)
local w = testWidth
if category.superCategory.x3 < w then
category.superCategory.x3 = w
end
else
local w = MIN_TOOLTIP_SIZE / 2
if category.superCategory.x3 < w then
category.superCategory.x3 = w
end
end
end
if columns >= 4 then
if self.text4 then
if not self.wrap4 then
local testWidth = getTestWidth(self.font4, self.size4 * fontSizePercent, self.text4)
w = testWidth
if category.superCategory.x4 < w then
category.superCategory.x4 = w
end
else
local w = MIN_TOOLTIP_SIZE / 2
if category.superCategory.x4 < w then
category.superCategory.x4 = w
end
end
end
if columns >= 5 then
if self.text5 then
if not self.wrap5 then
local testWidth = getTestWidth(self.font5, self.size5 * fontSizePercent, self.text5)
w = testWidth
if category.superCategory.x5 < w then
category.superCategory.x5 = w
end
else
local w = MIN_TOOLTIP_SIZE / 2
if category.superCategory.x5 < w then
category.superCategory.x5 = w
end
end
end
if columns >= 6 then
if self.text6 then
if not self.wrap6 then
local testWidth = getTestWidth(self.font6, self.size6 * fontSizePercent, self.text6)
w = testWidth
if category.superCategory.x6 < w then
category.superCategory.x6 = w
end
else
local w = MIN_TOOLTIP_SIZE / 2
if category.superCategory.x6 < w then
category.superCategory.x6 = w
end
end
end
end
end
end
end
return self
end
function Line:del()
del(self)
end
function Line:Display(tablet)
tablet:AddLine(self)
return true
end
end
local function button_OnEnter()
if type(this.self:GetScript("OnEnter")) == "function" then
this.self:GetScript("OnEnter")()
end
this.highlight:Show()
end
local function button_OnLeave()
if type(this.self:GetScript("OnLeave")) == "function" then
this.self:GetScript("OnLeave")()
end
this.highlight:Hide()
end
local num_buttons = 0
local function NewLine(self)
if self.maxLines <= self.numLines then
self.maxLines = self.maxLines + 1
num_buttons = num_buttons + 1
local button = CreateFrame("Button", "Tablet20Button" .. num_buttons, self)
button:SetFrameLevel(self:GetFrameLevel()+2)
button.indentation = 0
local check = button:CreateTexture(nil, "ARTWORK")
local left = button:CreateFontString(nil, "ARTWORK")
testString = left
local right = button:CreateFontString(nil, "ARTWORK")
local third = button:CreateFontString(nil, "ARTWORK")
local fourth = button:CreateFontString(nil, "ARTWORK")
local fifth = button:CreateFontString(nil, "ARTWORK")
local sixth = button:CreateFontString(nil, "ARTWORK")
local highlight = button:CreateTexture(nil, "BACKGROUND")
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
button.highlight = highlight
highlight:SetBlendMode("ADD")
highlight:SetAllPoints(button)
highlight:Hide()
table.insert(self.buttons, button)
table.insert(self.checks, check)
table.insert(self.lefts, left)
table.insert(self.rights, right)
table.insert(self.thirds, third)
table.insert(self.fourths, fourth)
table.insert(self.fifths, fifth)
table.insert(self.sixths, sixth)
left:SetWidth(0)
if self.maxLines == 1 then
left:SetFontObject(GameTooltipHeaderText)
right:SetFontObject(GameTooltipHeaderText)
third:SetFontObject(GameTooltipHeaderText)
fourth:SetFontObject(GameTooltipHeaderText)
fifth:SetFontObject(GameTooltipHeaderText)
sixth:SetFontObject(GameTooltipHeaderText)
left:SetJustifyH("CENTER")
button:SetPoint("TOPLEFT", self, "TOPLEFT", 8, -10)
else
left:SetFontObject(GameTooltipText)
right:SetFontObject(GameTooltipText)
third:SetFontObject(GameTooltipText)
fourth:SetFontObject(GameTooltipText)
fifth:SetFontObject(GameTooltipText)
sixth:SetFontObject(GameTooltipText)
button:SetPoint("TOPLEFT", self.buttons[self.maxLines - 1], "BOTTOMLEFT", 0, -2)
end
button:SetScript("OnEnter", button_OnEnter)
button:SetScript("OnLeave", button_OnLeave)
button.check = check
button.self = self
button:SetPoint("RIGHT", self, "RIGHT", -12, 0)
check.shown = false
check:SetPoint("TOPLEFT", button, "TOPLEFT")
left:SetPoint("TOPLEFT", check, "TOPLEFT")
right:SetPoint("TOPLEFT", left, "TOPRIGHT", 40 * self.fontSizePercent, 0)
third:SetPoint("TOPLEFT", right, "TOPRIGHT", 20 * self.fontSizePercent, 0)
fourth:SetPoint("TOPLEFT", third, "TOPRIGHT", 20 * self.fontSizePercent, 0)
fifth:SetPoint("TOPLEFT", fourth, "TOPRIGHT", 20 * self.fontSizePercent, 0)
sixth:SetPoint("TOPLEFT", fifth, "TOPRIGHT", 20 * self.fontSizePercent, 0)
right:SetJustifyH("RIGHT")
local _,size = GameTooltipText:GetFont()
check:SetHeight(size * 1.5)
check:SetWidth(size * 1.5)
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
check:SetAlpha(0)
if not button.clicked then
button:SetScript("OnMouseWheel", self:GetScript("OnMouseWheel"))
button:EnableMouseWheel(true)
button:Hide()
end
check:Show()
left:Hide()
right:Hide()
third:Hide()
fourth:Hide()
fifth:Hide()
sixth:Hide()
end
end
NewLine = wrap(NewLine, "NewLine")
local function GetMaxLinesPerScreen(self)
if self.height_ then
local height = self:GetTop() and self:GetBottom() and self:GetTop() - self:GetBottom() or self:GetHeight()
if height == 0 then
height = self.height_
end
height = height - 20
return floor(height / (12*self.fontSizePercent+2))
end
if self == tooltip then
return floor(50 / self.fontSizePercent)
else
return floor(30 / self.fontSizePercent)
end
end
GetMaxLinesPerScreen = wrap(GetMaxLinesPerScreen, "GetMaxLinesPerScreen")
local overFrame = nil
local detachedTooltips = {}
local AcquireDetachedFrame, ReleaseDetachedFrame
local function AcquireFrame(self, registration, data, detachedData)
if not detachedData then
detachedData = data
end
if tooltip then
tooltip.data = data
tooltip.detachedData = detachedData
local fontSizePercent = tooltip.data and tooltip.data.fontSizePercent or 1
local transparency = tooltip.data and tooltip.data.transparency or 0.75
local r = tooltip.data and tooltip.data.r or 0
local g = tooltip.data and tooltip.data.g or 0
local b = tooltip.data and tooltip.data.b or 0
tooltip:SetFontSizePercent(fontSizePercent)
tooltip:SetTransparency(transparency)
tooltip:SetColor(r, g, b)
tooltip:SetFrameStrata(registration.strata or "TOOLTIP")
else
tooltip = CreateFrame("Frame", "Tablet20Frame", UIParent)
self.tooltip = tooltip
tooltip.data = data
tooltip.detachedData = detachedData
tooltip:EnableMouse(true)
tooltip:EnableMouseWheel(true)
tooltip:SetFrameStrata(registration.strata or "TOOLTIP")
tooltip:SetFrameLevel(10)
local backdrop = new(
'bgFile', "Interface\\Buttons\\WHITE8X8",
'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border",
'tile', true,
'tileSize', 16,
'edgeSize', 16,
'insets', new(
'left', 5,
'right', 5,
'top', 5,
'bottom', 5
)
)
tooltip:SetBackdrop(backdrop)
del(backdrop.insets)
del(backdrop)
tooltip:SetBackdropColor(0, 0, 0, 1)
tooltip.numLines = 0
tooltip.owner = nil
tooltip.fontSizePercent = tooltip.data and tooltip.data.fontSizePercent or 1
tooltip.maxLines = 0
tooltip.buttons = {}
tooltip.checks = {}
tooltip.lefts = {}
tooltip.rights = {}
tooltip.thirds = {}
tooltip.fourths = {}
tooltip.fifths = {}
tooltip.sixths = {}
tooltip.transparency = tooltip.data and tooltip.data.transparency or 0.75
tooltip:SetBackdropColor(0, 0, 0, tooltip.transparency)
tooltip:SetBackdropBorderColor(1, 1, 1, tooltip.transparency)
tooltip.scroll = 0
tooltip:SetScript("OnUpdate", function()
if not tooltip.updating and (not tooltip.enteredFrame or (overFrame and not MouseIsOver(overFrame))) then
tooltip.scroll = 0
tooltip:Hide()
tooltip.registration.tooltip = nil
tooltip.registration = nil
overFrame = nil
end
end)
tooltip:SetScript("OnEnter", function()
if tooltip.clickable then
tooltip.enteredFrame = true
overFrame = nil
end
end)
tooltip:SetScript("OnLeave", function()
if not tooltip.updating then
tooltip.enteredFrame = false
end
end)
tooltip:SetScript("OnMouseWheel", function()
tooltip.updating = true
tooltip:Scroll(arg1 < 0)
tooltip.updating = false
end)
NewLine(tooltip)
tooltip.scrollUp = tooltip:CreateFontString(nil, "ARTWORK")
tooltip.scrollUp:SetPoint("TOPLEFT", tooltip.buttons[1], "BOTTOMLEFT", 0, -2)
tooltip.scrollUp:SetPoint("RIGHT", tooltip, "RIGHT", 0, -10)
tooltip.scrollUp:SetFontObject(GameTooltipText)
tooltip.scrollUp:Hide()
local font,_,flags = tooltip.scrollUp:GetFont()
tooltip.scrollUp:SetFont(font, normalSize * tooltip.fontSizePercent, flags)
tooltip.scrollUp:SetJustifyH("CENTER")
tooltip.scrollUp:SetTextColor(1, 0.823529, 0)
tooltip.scrollUp:SetText(" ")
tooltip.scrollDown = tooltip:CreateFontString(nil, "ARTWORK")
tooltip.scrollDown:SetPoint("TOPLEFT", tooltip.buttons[1], "BOTTOMLEFT", 0, -2)
tooltip.scrollDown:SetPoint("RIGHT", tooltip, "RIGHT", 0, -10)
tooltip.scrollDown:SetFontObject(GameTooltipText)
tooltip.scrollDown:Hide()
local font,_,flags = tooltip.scrollUp:GetFont()
tooltip.scrollDown:SetFont(font, normalSize * tooltip.fontSizePercent, flags)
tooltip.scrollDown:SetJustifyH("CENTER")
tooltip.scrollDown:SetTextColor(1, 0.823529, 0)
tooltip.scrollDown:SetText(" ")
function tooltip:SetOwner(o)
self:Hide(o)
self.owner = o
end
tooltip.SetOwner = wrap(tooltip.SetOwner, "tooltip:SetOwner")
function tooltip:IsOwned(o)
return self.owner == o
end
tooltip.IsOwned = wrap(tooltip.IsOwned, "tooltip:IsOwned")
function tooltip:ClearLines(hide)
CleanCategoryPool(self)
for i = 1, self.numLines do
local button = self.buttons[i]
local check = self.checks[i]
if not button.clicked or hide then
button:Hide()
end
check.shown = false
check:SetAlpha(0)
end
self.numLines = 0
end
tooltip.ClearLines = wrap(tooltip.ClearLines, "tooltip:ClearLines")
function tooltip:NumLines()
return self.numLines
end
local lastWidth
local old_tooltip_Hide = tooltip.Hide
tooltip.__Hide = old_tooltip_Hide
function tooltip:Hide(newOwner)
if self == tooltip or newOwner == nil then
old_tooltip_Hide(self)
end
self:ClearLines(true)
self.owner = nil
self.lastWidth = nil
self.tmpHidden = nil
end
tooltip.Hide = wrap(tooltip.Hide, "tooltip:Hide")
local old_tooltip_Show = tooltip.Show
tooltip.__Show = old_tooltip_Show
function tooltip:Show(tabletData)
if self.owner == nil or self.notInUse then
return
end
if not self.tmpHidden then
old_tooltip_Show(self)
end
testString = self.lefts[1]
local maxWidth = tabletData and tabletData.width or self:GetWidth() - 20
local hasWrap = false
local screenWidth = GetScreenWidth()
local scrollMax = self.numLines
local maxLinesPerScreen = GetMaxLinesPerScreen(self)
if scrollMax > maxLinesPerScreen + self.scroll then
scrollMax = maxLinesPerScreen + self.scroll
end
local numColumns
local height = 20
if scrollMax ~= self.numLines then
self.scrollDown:SetWidth(maxWidth)
height = height + self.scrollDown:GetHeight() + 2
end
if self.scroll ~= 0 then
self.scrollUp:SetWidth(maxWidth)
height = height + self.scrollUp:GetHeight() + 2
end
self:SetWidth(maxWidth + 20)
local tmp = self.scroll + 1
if tmp ~= 1 then
tmp = tmp + 1
end
for i = 1, self.numLines do
if i < tmp or i > scrollMax or (i == scrollMax and i ~= self.numLines) then
self.buttons[i]:ClearAllPoints()
self.buttons[i]:Hide()
else
local button = self.buttons[i]
local left = self.lefts[i]
local right = self.rights[i]
local check = self.checks[i]
button:SetWidth(maxWidth)
button:SetHeight(math.max(left:GetHeight(), right:GetHeight()))
height = height + button:GetHeight() + 2
if i == self.scroll + 1 then
button:SetPoint("TOPLEFT", self, "TOPLEFT", 10, -10)
else
button:SetPoint("TOPLEFT", self.buttons[i - 1], "BOTTOMLEFT", 0, -2)
end
if button.clicked then
check:SetPoint("TOPLEFT", button, "TOPLEFT", button.indentation * self.fontSizePercent + (check.width - check:GetWidth()) / 2 + 1, -1)
else
check:SetPoint("TOPLEFT", button, "TOPLEFT", button.indentation * self.fontSizePercent + (check.width - check:GetWidth()) / 2, 0)
end
button:Show()
end
end
if self.scroll ~= 0 then
self.scrollUp:SetPoint("TOPLEFT", self, "TOPLEFT", 10, -10)
self.buttons[self.scroll + 2]:SetPoint("TOPLEFT", self.scrollUp, "BOTTOMLEFT", 0, -2)
self.scrollUp:SetText(SCROLL_UP .. " (" .. self.scroll + 2 .. " / " .. self.numLines .. ")")
self.scrollUp:Show()
else
self.scrollUp:Hide()
end
if scrollMax ~= self.numLines and self.buttons[scrollMax - 1] then
self.scrollDown:SetPoint("TOPLEFT", self.buttons[scrollMax - 1], "BOTTOMLEFT", 0, -2)
self.scrollDown:SetText(SCROLL_DOWN .. " (" .. scrollMax - 1 .. " / " .. self.numLines .. ")")
self.scrollDown:Show()
else
self.scrollDown:Hide()
end
self:SetHeight(height)
end
tooltip.Show = wrap(tooltip.Show, "tooltip:Show")
local lastMouseDown
local function button_OnClick()
if this.self:HasScript("OnClick") and type(this.self:GetScript("OnClick")) == "function" then
this.self:GetScript("OnClick")()
end
if arg1 == "RightButton" then
if this.self:HasScript("OnClick") and type(this.self:GetScript("OnClick")) == "function" then
this.self:GetScript("OnClick")()
end
elseif arg1 == "LeftButton" then
if this.self.preventClick == nil or GetTime() > this.self.preventClick and GetTime() < lastMouseDown + 0.5 then
this.self.preventClick = nil
this.self.updating = true
this.self.preventRefresh = true
this.func(unpack(this))
if this.self and this.self.registration then
this.self.preventRefresh = false
this.self:children()
this.self.updating = false
end
end
end
end
local function button_OnMouseUp()
if this.self:HasScript("OnMouseUp") and type(this.self:GetScript("OnMouseUp")) == "function" then
this.self:GetScript("OnMouseUp")()
end
if arg1 ~= "RightButton" then
if this.clicked then
local a,b,c,d,e = this.check:GetPoint(1)
this.check:SetPoint(a,b,c,d-1,e+1)
this.clicked = false
end
end
end
local function button_OnMouseDown()
if this.self:HasScript("OnMouseDown") and type(this.self:GetScript("OnMouseDown")) == "function" then
this.self:GetScript("OnMouseDown")()
end
lastMouseDown = GetTime()
if arg1 ~= "RightButton" then
local a,b,c,d,e = this.check:GetPoint(1)
this.check:SetPoint(a,b,c,d+1,e-1)
this.clicked = true
end
end
function tooltip:AddLine(info)
local category = info.category.superCategory
local maxWidth = category.tabletData.width
local text = info.blank and "\n" or info.text
local id = info.id
local func = info.func
local checked = info.checked
local isRadio = info.isRadio
local checkTexture = info.checkTexture
local fontSizePercent = self.fontSizePercent
if not info.font then
info.font = GameTooltipText
end
if not info.size then
_,info.size = info.font:GetFont()
end
local catStart = false
local columns = category and category.columns or 1
local x1, x2, x3, x4, x5, x6
if category then
x1, x2, x3, x4, x5, x6 = category.x1, category.x2, category.x3, category.x4, category.x5, category.x6
else
x1, x2, x3, x4, x5, x6 = 0, 0, 0, 0, 0, 0
end
if info.isTitle then
justAddedTitle = true
end
self.numLines = self.numLines + 1
NewLine(self)
self.lefts[self.numLines]:Show()
self.buttons[self.numLines]:Show()
num = self.numLines
local button = self.buttons[num]
button.indentation = info.indentation
local left = self.lefts[num]
-- testString = left
local right = self.rights[num]
local third = self.thirds[num]
local fourth = self.fourths[num]
local fifth = self.fifths[num]
local sixth = self.sixths[num]
local check = self.checks[num]
do -- if columns >= 1 then
left:SetWidth(0)
left:SetFontObject(info.font)
local font,_,flags = left:GetFont()
left:SetFont(font, info.size * fontSizePercent, flags)
left:SetText(text)
left:SetJustifyH(info.justify)
left:Show()
if info.textR and info.textG and info.textB then
left:SetTextColor(info.textR, info.textG, info.textB)
else
left:SetTextColor(1, 0.823529, 0)
end
if columns < 2 then
right:SetText(nil)
right:Hide()
right:SetPoint("TOPLEFT", left, "TOPRIGHT", 40 * fontSizePercent, 0)
right:SetPoint("TOPRIGHT", button, "TOPRIGHT", -5, 0)
third:SetText(nil)
third:Hide()
fourth:SetText(nil)
fourth:Hide()
fifth:SetText(nil)
fifth:Hide()
sixth:SetText(nil)
sixth:Hide()
else
right:SetFontObject(info.font2)
right:SetText(info.text2)
right:Show()
if info.text2R and info.text2G and info.text2B then
right:SetTextColor(info.text2R, info.text2G, info.text2B)
else
right:SetTextColor(1, 0.823529, 0)
end
local a,_,b = right:GetFont()
right:SetFont(a, info.size2 * fontSizePercent, b)
right:SetJustifyH(info.justify2)
if columns < 3 then
right:SetPoint("TOPLEFT", left, "TOPRIGHT", 40 * fontSizePercent, 0)
right:SetPoint("TOPRIGHT", button, "TOPRIGHT", -5, 0)
third:SetText(nil)
third:Hide()
fourth:SetText(nil)
fourth:Hide()
fifth:SetText(nil)
fifth:Hide()
sixth:SetText(nil)
sixth:Hide()
else
third:SetFontObject(info.font3)
third:SetText(info.text3)
third:Show()
if info.text3R and info.text3G and info.text3B then
third:SetTextColor(info.text3R, info.text3G, info.text3B)
else
third:SetTextColor(1, 0.823529, 0)
end
local a,_,b = third:GetFont()
third:SetFont(a, info.size3 * fontSizePercent, b)
right:ClearAllPoints()
right:SetPoint("TOPLEFT", left, "TOPRIGHT", (20 - info.indentation) * fontSizePercent, 0)
third:SetJustifyH(info.justify3)
if columns < 4 then
fourth:SetText(nil)
fourth:Hide()
fifth:SetText(nil)
fifth:Hide()
sixth:SetText(nil)
sixth:Hide()
else
fourth:SetFontObject(info.font4)
fourth:SetText(info.text4)
fourth:Show()
if info.text4R and info.text4G and info.text4B then
fourth:SetTextColor(info.text4R, info.text4G, info.text4B)
else
fourth:SetTextColor(1, 0.823529, 0)
end
local a,_,b = fourth:GetFont()
fourth:SetFont(a, info.size4 * fontSizePercent, b)
fourth:SetJustifyH(info.justify4)
if columns < 5 then
fifth:SetText(nil)
fifth:Hide()
sixth:SetText(nil)
sixth:Hide()
else
fifth:SetFontObject(info.font5)
fifth:SetText(info.text5)
fifth:Show()
if info.text5R and info.text5G and info.text5B then
fifth:SetTextColor(info.text5R, info.text5G, info.text5B)
else
fifth:SetTextColor(1, 0.823529, 0)
end
local a,_,b = fourth:GetFont()
fifth:SetFont(a, info.size5 * fontSizePercent, b)
fifth:SetJustifyH(info.justify5)
if columns < 6 then
sixth:SetText(nil)
sixth:Hide()
else
sixth:SetFontObject(info.font6)
sixth:SetText(info.text6)
sixth:Show()
if info.text5R and info.text6G and info.text6B then
sixth:SetTextColor(info.text6R, info.text6G, info.text6B)
else
sixth:SetTextColor(1, 0.823529, 0)
end
local a,_,b = fourth:GetFont()
sixth:SetFont(a, info.size6 * fontSizePercent, b)
sixth:SetJustifyH(info.justify6)
end
end
end
end
end
end
check:SetWidth(info.size * fontSizePercent)
check:SetHeight(info.size * fontSizePercent)
check.width = info.size * fontSizePercent
if info.hasCheck then
check.shown = true
check:Show()
if isRadio then
check:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton")
if info.checked then
check:SetAlpha(1)
check:SetTexCoord(0.25, 0.5, 0, 1)
else
check:SetAlpha(self.transparency)
check:SetTexCoord(0, 0.25, 0, 1)
end
else
if info.checkIcon then
check:SetTexture(info.checkIcon)
if string.sub(info.checkIcon, 1, 16) == "Interface\\Icons\\" then
check:SetTexCoord(0.05, 0.95, 0.05, 0.95)
else
check:SetTexCoord(0, 1, 0, 1)
end
else
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
check:SetWidth(info.size * fontSizePercent * 1.5)
check:SetHeight(info.size * fontSizePercent * 1.5)
check.width = info.size * fontSizePercent * 1.2
check:SetTexCoord(0, 1, 0, 1)
end
check:SetAlpha(info.checked and 1 or 0)
end
left:SetPoint("TOPLEFT", check, "TOPLEFT", check.width, 0)
else
left:SetPoint("TOPLEFT", check, "TOPLEFT")
end
if columns == 1 then
left:SetWidth(maxWidth)
elseif columns == 2 then
left:SetWidth(0)
right:SetWidth(0)
if info.wrap then
left:SetWidth(maxWidth - right:GetWidth() - 40 * fontSizePercent)
elseif info.wrap2 then
right:SetWidth(maxWidth - left:GetWidth() - 40 * fontSizePercent)
end
right:ClearAllPoints()
right:SetPoint("TOPRIGHT", button, "TOPRIGHT", 0, 0)
if not info.text2 then
left:SetJustifyH(info.justify or "LEFT")
end
elseif columns == 3 then
left:SetWidth(x1 - info.checkWidth)
right:SetWidth(x2)
third:SetWidth(x3)
right:ClearAllPoints()
local num = (category.tabletData.width - x1 - x2 - x3) / 2
right:SetPoint("TOPLEFT", left, "TOPRIGHT", num - info.indentation * fontSizePercent, 0)
third:SetPoint("TOPLEFT", right, "TOPRIGHT", num, 0)
elseif columns == 4 then
left:SetWidth(x1 - info.checkWidth)
right:SetWidth(x2)
third:SetWidth(x3)
fourth:SetWidth(x4)
local num = (category.tabletData.width - x1 - x2 - x3 - x4) / 3
right:SetPoint("TOPLEFT", left, "TOPRIGHT", num - info.indentation * fontSizePercent, 0)
third:SetPoint("TOPLEFT", right, "TOPRIGHT", num, 0)
fourth:SetPoint("TOPLEFT", third, "TOPRIGHT", num, 0)
elseif columns == 5 then
left:SetWidth(x1 - info.checkWidth)
right:SetWidth(x2)
third:SetWidth(x3)
fourth:SetWidth(x4)
fifth:SetWidth(x5)
local num = (category.tabletData.width - x1 - x2 - x3 - x4 - x5) / 4
right:SetPoint("TOPLEFT", left, "TOPRIGHT", num - info.indentation * fontSizePercent, 0)
third:SetPoint("TOPLEFT", right, "TOPRIGHT", num, 0)
fourth:SetPoint("TOPLEFT", third, "TOPRIGHT", num, 0)
fifth:SetPoint("TOPLEFT", fourth, "TOPRIGHT", num, 0)
elseif columns == 6 then
left:SetWidth(x1 - info.checkWidth)
right:SetWidth(x2)
third:SetWidth(x3)
fourth:SetWidth(x4)
fifth:SetWidth(x5)
sixth:SetWidth(x6)
local num = (category.tabletData.width - x1 - x2 - x3 - x4 - x5 - x6) / 5
right:SetPoint("TOPLEFT", left, "TOPRIGHT", num - info.indentation * fontSizePercent, 0)
third:SetPoint("TOPLEFT", right, "TOPRIGHT", num, 0)
fourth:SetPoint("TOPLEFT", third, "TOPRIGHT", num, 0)
fifth:SetPoint("TOPLEFT", fourth, "TOPRIGHT", num, 0)
sixth:SetPoint("TOPLEFT", fifth, "TOPRIGHT", num, 0)
end
if not self.locked or IsAltKeyDown() then
local func = info.func
if func then
if type(func) == "string" then
if type(info.arg1) ~= "table" then
Tablet:error("Cannot call method " .. info.func .. " on a non-table")
end
func = info.arg1[func]
if type(func) ~= "function" then
Tablet:error("Method " .. info.func .. " nonexistant")
end
else
if type(func) ~= "function" then
Tablet:error("func must be a function or method")
end
end
button.func = func
local i = 1
while true do
if button[i] ~= nil then
button[i] = nil
else
break
end
i = i + 1
end
i = 1
while true do
local k = 'arg' .. i
local v = info[k]
if v == nil then
break
end
button[i] = v
i = i + 1
end
button.self = self
button:SetScript("OnMouseUp", button_OnMouseUp)
button:SetScript("OnMouseDown", button_OnMouseDown)
button:SetScript("OnClick", button_OnClick)
if button.clicked then
button:SetButtonState("PUSHED")
end
button:EnableMouse(true)
else
button:SetScript("OnMouseDown", nil)
button:SetScript("OnMouseUp", nil)
button:SetScript("OnClick", nil)
button:EnableMouse(false)
end
else
button:SetScript("OnMouseDown", nil)
button:SetScript("OnMouseUp", nil)
button:SetScript("OnClick", nil)
button:EnableMouse(false)
end
end
tooltip.AddLine = wrap(tooltip.AddLine, "tooltip:AddLine")
function tooltip:SetFontSizePercent(percent)
local data, detachedData = self.data, self.detachedData
if detachedData and detachedData.detached then
data = detachedData
end
local lastSize = self.fontSizePercent
percent = tonumber(percent) or 1
if percent < 0.25 then
percent = 0.25
elseif percent > 4 then
percent = 4
end
self.fontSizePercent = percent
if data then
data.fontSizePercent = percent
end
self.scrollUp:SetFont(font, normalSize * self.fontSizePercent, flags)
self.scrollDown:SetFont(font, normalSize * self.fontSizePercent, flags)
local ratio = self.fontSizePercent / lastSize
for i = 1, self.numLines do
local left = self.lefts[i]
local right = self.rights[i]
local third = self.thirds[i]
local fourth = self.fourths[i]
local fifth = self.fifths[i]
local sixth = self.sixths[i]
local check = self.checks[i]
local font, size, flags = left:GetFont()
left:SetFont(font, size * ratio, flags)
font, size, flags = right:GetFont()
right:SetFont(font, size * ratio, flags)
font, size, flags = third:GetFont()
third:SetFont(font, size * ratio, flags)
font, size, flags = fourth:GetFont()
fourth:SetFont(font, size * ratio, flags)
font, size, flags = fifth:GetFont()
fifth:SetFont(font, size * ratio, flags)
font, size, flags = sixth:GetFont()
sixth:SetFont(font, size * ratio, flags)
check.width = check.width * ratio
check:SetWidth(check:GetWidth() * ratio)
check:SetHeight(check:GetHeight() * ratio)
end
self:SetWidth((self:GetWidth() - 51) * ratio + 51)
self:SetHeight((self:GetHeight() - 51) * ratio + 51)
if self:IsShown() and self.children then
self:children()
self:Show()
end
end
tooltip.SetFontSizePercent = wrap(tooltip.SetFontSizePercent, "tooltip:SetFontSizePercent")
function tooltip:GetFontSizePercent()
return self.fontSizePercent
end
function tooltip:SetTransparency(alpha)
local data, detachedData = self.data, self.detachedData
if detachedData and detachedData.detached then
data = detachedData
end
self.transparency = alpha
if data then
data.transparency = alpha ~= 0.75 and alpha or nil
end
self:SetBackdropColor(self.r or 0, self.g or 0, self.b or 0, alpha)
self:SetBackdropBorderColor(1, 1, 1, alpha)
end
tooltip.SetTransparency = wrap(tooltip.SetTransparency, "tooltip:SetTransparency")
function tooltip:GetTransparency()
return self.transparency
end
function tooltip:SetColor(r, g, b)
local data, detachedData = self.data, self.detachedData
if detachedData and detachedData.detached then
data = detachedData
end
self.r = r
self.g = g
self.b = b
if data then
data.r = r ~= 0 and r or nil
data.g = g ~= 0 and g or nil
data.b = b ~= 0 and b or nil
end
self:SetBackdropColor(r or 0, g or 0, b or 0, self.transparency)
self:SetBackdropBorderColor(1, 1, 1, self.transparency)
end
tooltip.SetColor = wrap(tooltip.SetColor, "tooltip:SetColor")
function tooltip:GetColor()
return self.r, self.g, self.b
end
function tooltip:Scroll(down)
local maxLinesPerScreen = GetMaxLinesPerScreen(self)
if down then
if IsShiftKeyDown() then
self.scroll = self.numLines - maxLinesPerScreen
else
self.scroll = self.scroll + 3
end
else
if IsShiftKeyDown() then
self.scroll = 0
else
self.scroll = self.scroll - 3
end
end
if self.scroll > self.numLines - maxLinesPerScreen then
self.scroll = self.numLines - maxLinesPerScreen
end
if self.scroll < 0 then
self.scroll = 0
end
if self:IsShown() then
self:Show()
end
end
tooltip.Scroll = wrap(tooltip.Scroll, "tooltip:Scroll")
function tooltip.Detach(tooltip)
local owner = tooltip.owner
tooltip:Hide()
if not tooltip.detachedData then
self:error("You cannot detach if detachedData is not present")
end
tooltip.detachedData.detached = true
local detached = AcquireDetachedFrame(self, tooltip.registration, tooltip.data, tooltip.detachedData)
detached.menu, tooltip.menu = tooltip.menu, nil
detached.children = tooltip.children
tooltip.children = nil
detached:SetOwner(owner)
detached:children()
detached:Show()
end
tooltip.Detach = wrap(tooltip.Detach, "tooltip:Detach")
end
tooltip.registration = registration
registration.tooltip = tooltip
return tooltip
end
AcquireFrame = wrap(AcquireFrame, "AcquireFrame")
function ReleaseDetachedFrame(self, data, detachedData)
if not detachedData then
detachedData = data
end
for _, detached in ipairs(detachedTooltips) do
if detached.detachedData == detachedData then
detached.notInUse = true
detached:Hide()
detached.registration.tooltip = nil
detached.registration = nil
detached.detachedData = nil
end
end
end
ReleaseDetachedFrame = wrap(ReleaseDetachedFrame, "ReleaseDetachedFrame")
local StartCheckingAlt, StopCheckingAlt
do
local frame
function StartCheckingAlt(func)
if not frame then
frame = CreateFrame("Frame")
frame:SetScript("OnEvent", function(this, _, modifier)
if modifier == "ALT" then
this.func()
end
end)
end
frame:RegisterEvent("MODIFIER_STATE_CHANGED")
frame.func = func
end
function StopCheckingAlt()
if frame then
frame:UnregisterEvent("MODIFIER_STATE_CHANGED")
end
end
end
local fake_ipairs
do
local function iter(tmp, i)
i = i + 1
local x = tmp[i]
tmp[i] = nil
if x then
return i, x
end
end
local tmp = {}
function fake_ipairs(...)
for i = 1, select('#', ...) do
tmp[i] = select(i, ...)
end
return iter, tmp, 0
end
end
function AcquireDetachedFrame(self, registration, data, detachedData)
if not detachedData then
detachedData = data
end
for _, detached in ipairs(detachedTooltips) do
if detached.notInUse then
detached.data = data
detached.detachedData = detachedData
detached.notInUse = nil
local fontSizePercent = detachedData.fontSizePercent or 1
local transparency = detachedData.transparency or 0.75
local r = detachedData.r or 0
local g = detachedData.g or 0
local b = detachedData.b or 0
detached:SetFontSizePercent(fontSizePercent)
detached:SetTransparency(transparency)
detached:SetColor(r, g, b)
detached:ClearAllPoints()
detached:SetWidth(0)
detached:SetHeight(0)
if not registration.strata then
detached:SetFrameStrata("BACKGROUND")
end
if not registration.frameLevel then
detached:SetFrameLevel(10)
for _,frame in fake_ipairs(detached:GetChildren()) do
frame:SetFrameLevel(12)
end
end
detached:SetParent(registration.parent or UIParent)
if registration.strata then
detached:SetFrameStrata(registration.strata)
end
if registration.frameLevel then
detached:SetFrameLevel(registration.frameLevel)
for _,frame in fake_ipairs(detached:GetChildren()) do
frame:SetFrameLevel(registration.frameLevel+2)
end
end
detached.height_ = nil
if registration.positionFunc then
registration.positionFunc(detached)
local height = detached:GetHeight()
if height > 0 then
detached.height_ = height
else
local top, bottom
for i = 1, detached:GetNumPoints() do
local a,b,c,d,e = detached:GetPoint(i)
if a:find("^TOP") then
if c:find("^TOP") then
top = b:GetTop()
elseif c:find("^BOTTOM") then
top = b:GetBottom()
else
_,top = b:GetCenter()
end
if top then
top = top + e
end
elseif a:find("^BOTTOM") then
if c:find("^TOP") then
bottom = b:GetTop()
elseif c:find("^BOTTOM") then
bottom = b:GetBottom()
else
_,bottom = b:GetCenter()
end
if bottom then
bottom = bottom + e
end
end
end
if top and bottom then
detached.height_ = top - bottom
end
end
else
detached:SetPoint(detachedData.anchor or "CENTER", UIParent, detachedData.anchor or "CENTER", detachedData.offsetx or 0, detachedData.offsety or 0)
end
detached.registration = registration
registration.tooltip = detached
if registration.movable == false then
detached:RegisterForDrag()
else
detached:RegisterForDrag("LeftButton")
end
return detached
end
end
if not Dewdrop and AceLibrary:HasInstance("Dewdrop-2.0") then
Dewdrop = AceLibrary("Dewdrop-2.0")
end
StartCheckingAlt(function()
for _, detached in ipairs(detachedTooltips) do
if detached:IsShown() and detached.locked then
detached:EnableMouse(IsAltKeyDown())
detached:children()
if detached.moving then
local a1 = arg1
arg1 = "LeftButton"
if type(detached:GetScript("OnMouseUp")) == "function" then
detached:GetScript("OnMouseUp")(detached, arg1)
end
arg1 = a1
end
end
end
end)
if not tooltip then
AcquireFrame(self, {})
end
local detached = CreateFrame("Frame", "Tablet20DetachedFrame" .. (#detachedTooltips + 1), UIParent)
table.insert(detachedTooltips, detached)
detached.notInUse = true
detached:EnableMouse(not data.locked)
detached:EnableMouseWheel(true)
detached:SetMovable(true)
detached:SetPoint(data.anchor or "CENTER", UIParent, data.anchor or "CENTER", data.offsetx or 0, data.offsety or 0)
detached.numLines = 0
detached.owner = nil
detached.fontSizePercent = 1
detached.maxLines = 0
detached.buttons = {}
detached.checks = {}
detached.lefts = {}
detached.rights = {}
detached.thirds = {}
detached.fourths = {}
detached.fifths = {}
detached.sixths = {}
detached.transparency = 0.75
detached.r = 0
detached.g = 0
detached.b = 0
detached:SetFrameStrata(registration.strata or "BACKGROUND")
detached:SetBackdrop(tmp.a(
'bgFile', "Interface\\Buttons\\WHITE8X8",
'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border",
'tile', true,
'tileSize', 16,
'edgeSize', 16,
'insets', tmp.b(
'left', 5,
'right', 5,
'top', 5,
'bottom', 5
)
))
detached.locked = detachedData.locked
detached.scroll = 0
detached:EnableMouse(not detached.locked)
local width = GetScreenWidth()
local height = GetScreenHeight()
if registration.movable == false then
detached:RegisterForDrag()
else
detached:RegisterForDrag("LeftButton")
end
detached:SetScript("OnDragStart", function()
detached:StartMoving()
detached.moving = true
end)
detached:SetScript("OnDragStop", function()
detached:StopMovingOrSizing()
detached.moving = nil
local anchor
local offsetx
local offsety
if detached:GetTop() + detached:GetBottom() < height then
anchor = "BOTTOM"
offsety = detached:GetBottom()
if offsety < 0 then
offsety = 0
end
if offsety < MainMenuBar:GetTop() and MainMenuBar:IsVisible() then
offsety = MainMenuBar:GetTop()
end
local top = 0
if FuBar then
for i = 1, FuBar:GetNumPanels() do
local panel = FuBar:GetPanel(i)
if panel:GetAttachPoint() == "BOTTOM" then
if panel.frame:GetTop() > top then
top = panel.frame:GetTop()
break
end
end
end
end
if offsety < top then
offsety = top
end
else
anchor = "TOP"
offsety = detached:GetTop() - height
if offsety > 0 then
offsety = 0
end
local bottom = GetScreenHeight()
if FuBar then
for i = 1, FuBar:GetNumPanels() do
local panel = FuBar:GetPanel(i)
if panel:GetAttachPoint() == "TOP" then
if panel.frame:GetBottom() < bottom then
bottom = panel.frame:GetBottom()
break
end
end
end
end
bottom = bottom - GetScreenHeight()
if offsety > bottom then
offsety = bottom
end
end
if detached:GetLeft() + detached:GetRight() < width * 2 / 3 then
anchor = anchor .. "LEFT"
offsetx = detached:GetLeft()
if offsetx < 0 then
offsetx = 0
end
elseif detached:GetLeft() + detached:GetRight() < width * 4 / 3 then
if anchor == "" then
anchor = "CENTER"
end
offsetx = (detached:GetLeft() + detached:GetRight() - GetScreenWidth()) / 2
else
anchor = anchor .. "RIGHT"
offsetx = detached:GetRight() - width
if offsetx > 0 then
offsetx = 0
end
end
detached:ClearAllPoints()
detached:SetPoint(anchor, UIParent, anchor, offsetx, offsety)
local t = detached.detachedData
if t.anchor ~= anchor or math.abs(t.offsetx - offsetx) > 8 or math.abs(t.offsety - offsety) > 8 then
detached.preventClick = GetTime() + 0.05
end
t.anchor = anchor
t.offsetx = offsetx
t.offsety = offsety
detached:Show()
end)
if Dewdrop then
Dewdrop:Register(detached,
'children', function(level, value)
if not detached.registration then
return
end
if detached.menu then
detached.menu(level, value)
if level == 1 then
Dewdrop:AddLine()
end
end
if level == 1 then
if not detached.registration.cantAttach then
Dewdrop:AddLine(
'text', DETACH,
'tooltipTitle', DETACH,
'tooltipText', DETACH_DESC,
'checked', true,
'arg1', detached,
'func', "Attach",
'closeWhenClicked', true
)
end
Dewdrop:AddLine(
'text', LOCK,
'tooltipTitle', LOCK,
'tooltipText', LOCK_DESC,
'checked', detached:IsLocked(),
'arg1', detached,
'func', "Lock",
'closeWhenClicked', not detached:IsLocked()
)
Dewdrop:AddLine(
'text', COLOR,
'tooltipTitle', COLOR,
'tooltipText', COLOR_DESC,
'hasColorSwatch', true,
'r', detached.r,
'g', detached.g,
'b', detached.b,
'hasOpacity', true,
'opacity', detached.transparency,
'colorFunc', function(r, g, b, a)
detached:SetColor(r, g, b)
detached:SetTransparency(a)
end
)
Dewdrop:AddLine(
'text', SIZE,
'tooltipTitle', SIZE,
'tooltipText', SIZE_DESC,
'hasArrow', true,
'hasSlider', true,
'sliderFunc', function(value)
detached:SetFontSizePercent(value)
end,
'sliderMax', 2,
'sliderMin', 0.5,
'sliderStep', 0.05,
'sliderIsPercent', true,
'sliderValue', detached:GetFontSizePercent()
)
Dewdrop:AddLine(
'text', CLOSE_MENU,
'tooltipTitle', CLOSE_MENU,
'tooltipText', CLOSE_MENU_DESC,
'func', function()
Dewdrop:Close()
end
)
end
end,
'point', function()
local x, y = detached:GetCenter()
if x < GetScreenWidth() / 2 then
if y < GetScreenHeight() / 2 then
return "BOTTOMLEFT", "BOTTOMRIGHT"
else
return "TOPLEFT", "TOPRIGHT"
end
else
if y < GetScreenHeight() / 2 then
return "BOTTOMRIGHT", "BOTTOMLEFT"
else
return "TOPRIGHT", "TOPLEFT"
end
end
end
)
end
NewLine(detached)
detached.scrollUp = detached:CreateFontString(nil, "ARTWORK")
detached.scrollUp:SetPoint("TOPLEFT", detached.buttons[1], "BOTTOMLEFT", 0, -2)
detached.scrollUp:SetPoint("RIGHT", detached, "RIGHT", 0, -10)
detached.scrollUp:SetFontObject(GameTooltipText)
detached.scrollUp:Hide()
local font,_,flags = detached.scrollUp:GetFont()
detached.scrollUp:SetFont(font, normalSize * detached.fontSizePercent, flags)
detached.scrollUp:SetJustifyH("CENTER")
detached.scrollUp:SetTextColor(1, 0.823529, 0)
detached.scrollUp:SetText(" ")
detached.scrollDown = detached:CreateFontString(nil, "ARTWORK")
detached.scrollDown:SetPoint("TOPLEFT", detached.buttons[1], "BOTTOMLEFT", 0, -2)
detached.scrollDown:SetPoint("RIGHT", detached, "RIGHT", 0, -10)
detached.scrollDown:SetFontObject(GameTooltipText)
detached.scrollDown:Hide()
local font,_,flags = detached.scrollUp:GetFont()
detached.scrollDown:SetFont(font, normalSize * detached.fontSizePercent, flags)
detached.scrollDown:SetJustifyH("CENTER")
detached.scrollDown:SetTextColor(1, 0.823529, 0)
detached.scrollDown:SetText(" ")
detached:SetScript("OnMouseWheel", function()
detached:Scroll(arg1 < 0)
end)
detached.SetTransparency = tooltip.SetTransparency
detached.GetTransparency = tooltip.GetTransparency
detached.SetColor = tooltip.SetColor
detached.GetColor = tooltip.GetColor
detached.SetFontSizePercent = tooltip.SetFontSizePercent
detached.GetFontSizePercent = tooltip.GetFontSizePercent
detached.SetOwner = tooltip.SetOwner
detached.IsOwned = tooltip.IsOwned
detached.ClearLines = tooltip.ClearLines
detached.NumLines = tooltip.NumLines
detached.__Hide = detached.Hide
detached.__Show = detached.Show
detached.Hide = tooltip.Hide
detached.Show = tooltip.Show
local old_IsShown = detached.IsShown
function detached:IsShown()
if self.tmpHidden then
return true
else
return old_IsShown(self)
end
end
detached.AddLine = tooltip.AddLine
detached.Scroll = tooltip.Scroll
function detached:IsLocked()
return self.locked
end
function detached:Lock()
self:EnableMouse(self.locked)
self.locked = not self.locked
self.detachedData.locked = self.locked or nil
self:children()
end
function detached.Attach(detached)
if not detached then
self:error("Detached tooltip not given.")
end
if not detached.AddLine then
self:error("detached argument not a Tooltip.")
end
if not detached.owner then
self:error("Detached tooltip has no owner.")
end
if detached.notInUse then
self:error("Detached tooltip not in use.")
end
detached.menu = nil
detached.detachedData.detached = nil
detached:SetOwner(nil)
detached.notInUse = true
end
return AcquireDetachedFrame(self, registration, data, detachedData)
end
AcquireDetachedFrame = wrap(AcquireDetachedFrame, "AcquireDetachedFrame")
function Tablet:Close(parent)
if not parent then
if tooltip and tooltip:IsShown() then
tooltip:Hide()
tooltip.registration.tooltip = nil
tooltip.registration = nil
tooltip.enteredFrame = false
end
return
else
self:argCheck(parent, 2, "table", "string")
end
local info = self.registry[parent]
if not info then
self:error("You cannot close a tablet with an unregistered parent frame.")
end
local data = info.data
local detachedData = info.detachedData
if detachedData and detachedData.detached then
ReleaseDetachedFrame(self, data, detachedData)
elseif tooltip.data == data then
tooltip:Hide()
tooltip.registration.tooltip = nil
tooltip.registration = nil
end
tooltip.enteredFrame = false
end
Tablet.Close = wrap(Tablet.Close, "Tablet:Close")
local currentFrame
local currentTabletData
function Tablet:Open(fakeParent, parent)
self:argCheck(fakeParent, 2, "table", "string")
self:argCheck(parent, 3, "nil", "table", "string")
if not parent then
parent = fakeParent
end
local info = self.registry[parent]
if not info then
self:error("You cannot open a tablet with an unregistered parent frame.")
end
local detachedData = info.detachedData
if detachedData then
for _, detached in ipairs(detachedTooltips) do
if not detached.notInUse and detached.detachedData == detachedData then
return
end
end
end
-- self:Close(fakeParent)
local data = info.data
local children = info.children
if not children then
return
end
local frame = AcquireFrame(self, info, data, detachedData)
frame.clickable = info.clickable
frame.menu = info.menu
local children = info.children
function frame:children()
if not self.preventRefresh and self:GetParent():IsVisible() then
currentFrame = self
currentTabletData = TabletData:new(self)
-- if info.width then
-- currentTabletData.width = info.width
-- end
self:ClearLines()
if children then
children()
end
currentTabletData:Display(currentFrame)
self:Show(currentTabletData)
currentTabletData:del()
currentTabletData = nil
currentFrame = nil
end
end
frame:SetOwner(fakeParent)
frame:children()
local point = info.point
local relativePoint = info.relativePoint
if type(point) == "function" then
local b
point, b = point(fakeParent)
if b then
relativePoint = b
end
end
if type(relativePoint) == "function" then
relativePoint = relativePoint(fakeParent)
end
if not point then
point = "CENTER"
end
if not relativePoint then
relativePoint = point
end
frame:ClearAllPoints()
if type(parent) ~= "string" then
frame:SetPoint(point, fakeParent, relativePoint)
end
local offsetx = 0
local offsety = 0
if frame:GetBottom() and frame:GetLeft() then
if frame:GetRight() > GetScreenWidth() then
offsetx = frame:GetRight() - GetScreenWidth()
elseif frame:GetLeft() < 0 then
offsetx = -frame:GetLeft()
end
local ratio = GetScreenWidth() / GetScreenHeight()
if ratio >= 2.4 and frame:GetRight() > GetScreenWidth() / 2 and frame:GetLeft() < GetScreenWidth() / 2 then
if frame:GetCenter() < GetScreenWidth() / 2 then
offsetx = frame:GetRight() - GetScreenWidth() / 2
else
offsetx = frame:GetLeft() - GetScreenWidth() / 2
end
end
if frame:GetBottom() < 0 then
offsety = frame:GetBottom()
elseif frame:GetTop() and frame:GetTop() > GetScreenHeight() then
offsety = frame:GetTop() - GetScreenHeight()
end
if MainMenuBar:IsVisible() and frame:GetBottom() < MainMenuBar:GetTop() and offsety < frame:GetBottom() - MainMenuBar:GetTop() then
offsety = frame:GetBottom() - MainMenuBar:GetTop()
end
if FuBar then
local top = 0
if FuBar then
for i = 1, FuBar:GetNumPanels() do
local panel = FuBar:GetPanel(i)
if panel:GetAttachPoint() == "BOTTOM" then
if panel.frame:GetTop() and panel.frame:GetTop() > top then
top = panel.frame:GetTop()
break
end
end
end
end
if frame:GetBottom() < top and offsety < frame:GetBottom() - top then
offsety = frame:GetBottom() - top
end
local bottom = GetScreenHeight()
if FuBar then
for i = 1, FuBar:GetNumPanels() do
local panel = FuBar:GetPanel(i)
if panel:GetAttachPoint() == "TOP" then
if panel.frame:GetBottom() and panel.frame:GetBottom() < bottom then
bottom = panel.frame:GetBottom()
break
end
end
end
end
if frame:GetTop() > bottom and offsety < frame:GetTop() - bottom then
offsety = frame:GetTop() - bottom
end
end
end
if type(fakeParent) ~= "string" then
frame:SetPoint(point, fakeParent, relativePoint, -offsetx, -offsety)
end
if detachedData and (info.cantAttach or detachedData.detached) and frame == tooltip then
detachedData.detached = false
frame:Detach()
end
if (not detachedData or not detachedData.detached) and GetMouseFocus() == fakeParent then
self.tooltip.enteredFrame = true
end
overFrame = type(fakeParent) == "table" and MouseIsOver(fakeParent) and fakeParent
end
Tablet.Open = wrap(Tablet.Open, "Tablet:Open")
function Tablet:Register(parent, ...)
self:argCheck(parent, 2, "table", "string")
if self.registry[parent] then
self:Unregister(parent)
end
local info
local k1 = ...
if type(k1) == "table" and k1[0] then
if type(self.registry[k1]) ~= "table" then
self:error("Other parent not registered")
end
info = copy(self.registry[k1])
local v1 = select(2, ...)
if type(v1) == "function" then
info.point = v1
info.relativePoint = nil
end
else
info = new(...)
end
self.registry[parent] = info
info.data = info.data or info.detachedData or {}
info.detachedData = info.detachedData or info.data
local data = info.data
local detachedData = info.detachedData
if not self.onceRegistered[parent] and type(parent) == "table" and type(parent.SetScript) == "function" and not info.dontHook then
if not Dewdrop and AceLibrary:HasInstance("Dewdrop-2.0") then
Dewdrop = AceLibrary("Dewdrop-2.0")
end
local script = parent:GetScript("OnEnter")
parent:SetScript("OnEnter", function(...)
if script then
script(...)
end
if self.registry[parent] then
if (not data or not detachedData.detached) and (Dewdrop and not Dewdrop:IsOpen(parent)) then
self:Open(parent)
end
end
end)
if parent:HasScript("OnMouseDown") then
local script = parent:GetScript("OnMouseDown")
parent:SetScript("OnMouseDown", function(...)
if script then
script(...)
end
if self.registry[parent] and self.registry[parent].tooltip and self.registry[parent].tooltip == self.tooltip then
self.tooltip:Hide()
end
end)
end
if parent:HasScript("OnMouseWheel") then
local script = parent:GetScript("OnMouseWheel")
parent:SetScript("OnMouseWheel", function(...)
if script then
script(...)
end
if self.registry[parent] and self.registry[parent].tooltip then
self.registry[parent].tooltip:Scroll(arg1 < 0)
end
end)
end
end
self.onceRegistered[parent] = true
if GetMouseFocus() == parent then
self:Open(parent)
end
end
Tablet.Register = wrap(Tablet.Register, "Tablet:Register")
function Tablet:Unregister(parent)
self:argCheck(parent, 2, "table", "string")
if not self.registry[parent] then
self:error("You cannot unregister a parent frame if it has not been registered already.")
end
self.registry[parent] = nil
end
Tablet.Unregister = wrap(Tablet.Unregister, "Tablet:Unregister")
function Tablet:IsRegistered(parent)
self:argCheck(parent, 2, "table", "string")
return self.registry[parent] and true
end
Tablet.IsRegistered = wrap(Tablet.IsRegistered, "Tablet:IsRegistered")
local _id = 0
local addedCategory
local currentCategoryInfo
local depth = 0
local categoryPool = {}
function CleanCategoryPool(self)
for k,v in pairs(categoryPool) do
del(v)
categoryPool[k] = nil
end
_id = 0
end
function Tablet:AddCategory(...)
if not currentFrame then
self:error("You must add categories in within a registration.")
end
local info = new(...)
local cat = currentTabletData:AddCategory(info)
info = del(info)
return cat
end
Tablet.AddCategory = wrap(Tablet.AddCategory, "Tablet:AddCategory")
function Tablet:SetHint(text)
if not currentFrame then
self:error("You must set hint within a registration.")
end
if currentCategoryInfo then
self:error("You cannot set hint in a category.")
end
currentTabletData:SetHint(text)
end
Tablet.SetHint = wrap(Tablet.SetHint, "Tablet:SetHint")
function Tablet:SetTitle(text)
if not currentFrame then
self:error("You must set title within a registration.")
end
if currentCategoryInfo then
self:error("You cannot set title in a category.")
end
currentTabletData:SetTitle(text)
end
Tablet.SetTitle = wrap(Tablet.SetTitle, "Tablet:SetTitle")
function Tablet:SetTitleColor(r, g, b)
if not currentFrame then
self:error("You must set title color within a registration.")
end
if currentCategoryInfo then
self:error("You cannot set title color in a category.")
end
self:argCheck(r, 2, "number")
self:argCheck(g, 3, "number")
self:argCheck(b, 4, "number")
currentTabletData:SetTitleColor(r, g, b)
end
Tablet.SetTitleColor = wrap(Tablet.SetTitleColor, "Tablet:SetTitleColor")
function Tablet:GetNormalFontSize()
return normalSize
end
function Tablet:GetHeaderFontSize()
return headerSize
end
function Tablet:GetNormalFontObject()
return GameTooltipText
end
function Tablet:GetHeaderFontObject()
return GameTooltipHeaderText
end
function Tablet:SetFontSizePercent(parent, percent)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if info then
if info.tooltip then
info.tooltip:SetFontSizePercent(percent)
else
local data = info.data
local detachedData = info.detachedData
if detachedData.detached then
detachedData.fontSizePercent = percent
else
data.fontSizePercent = percent
end
end
elseif type(parent) == "table" then
parent.fontSizePercent = percent
else
self:error("You cannot change font size with an unregistered parent frame.")
end
end
Tablet.SetFontSizePercent = wrap(Tablet.SetFontSizePercent, "Tablet:SetFontSizePercent")
function Tablet:GetFontSizePercent(parent)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if info then
local data = info.data
local detachedData = info.detachedData
if detachedData.detached then
return detachedData.fontSizePercent or 1
else
return data.fontSizePercent or 1
end
elseif type(parent) == "table" then
return parent.fontSizePercent or 1
else
self:error("You cannot check font size with an unregistered parent frame.")
end
end
Tablet.GetFontSizePercent = wrap(Tablet.GetFontSizePercent, "Tablet:GetFontSizePercent")
function Tablet:SetTransparency(parent, percent)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if info then
if info.tooltip then
info.tooltip:SetTransparency(percent)
else
local data = info.data
local detachedData = info.detachedData
if detachedData.detached then
detachedData.transparency = percent
elseif data then
data.transparency = percent
end
end
elseif type(parent) == "table" then
parent.transparency = percent
else
self:error("You cannot change transparency with an unregistered parent frame.")
end
end
Tablet.SetTransparency = wrap(Tablet.SetTransparency, "Tablet:SetTransparency")
function Tablet:GetTransparency(parent)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if info then
local data = info.data
local detachedData = info.detachedData
if detachedData.detached then
return detachedData.transparency or 0.75
else
return data.transparency or 0.75
end
elseif type(parent) == "table" then
return parent.transparency or 0.75
else
self:error("You cannot get transparency with an unregistered parent frame.")
end
end
Tablet.GetTransparency = wrap(Tablet.GetTransparency, "Tablet:GetTransparency")
function Tablet:SetColor(parent, r, g, b)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if info then
if info.tooltip then
info.tooltip:SetColor(r, g, b)
else
local data = info.data
local detachedData = info.detachedData
if detachedData.detached then
detachedData.r = r
detachedData.g = g
detachedData.b = b
else
data.r = r
data.g = g
data.b = b
end
end
elseif type(parent) == "table" then
parent.r = r
parent.g = g
parent.b = b
else
self:error("You cannot change color with an unregistered parent frame.")
end
end
Tablet.SetColor = wrap(Tablet.SetColor, "Tablet:SetColor")
function Tablet:GetColor(parent)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if info then
local data = info.data
local detachedData = info.detachedData
if detachedData.detached then
return detachedData.r or 0, detachedData.g or 0, detachedData.b or 0
else
return data.r or 0, data.g or 0, data.b or 0
end
elseif type(parent) == "table" then
return parent.r or 0, parent.g or 0, parent.b or 0
else
self:error("You must provide a registered parent frame to check color")
end
end
Tablet.GetColor = wrap(Tablet.GetColor, "Tablet:GetColor")
function Tablet:Detach(parent)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if not info then
self:error("You cannot detach tablet with an unregistered parent frame.")
end
if not info.detachedData then
self:error("You cannot detach tablet without a data field.")
end
if info.tooltip and info.tooltip == tooltip then
tooltip:Detach()
else
info.detachedData.detached = true
local detached = AcquireDetachedFrame(self, info, info.data, info.detachedData)
detached.menu = info.menu
local children = info.children
function detached:children()
if not self.preventRefresh then
currentFrame = self
currentTabletData = TabletData:new(self)
self:ClearLines()
if children then
children()
end
currentTabletData:Display(currentFrame)
self:Show(currentTabletData)
currentTabletData:del()
currentTabletData = nil
currentFrame = nil
end
end
detached:SetOwner(parent)
detached:children()
end
end
Tablet.Detach = wrap(Tablet.Detach, "Tablet:Detach")
function Tablet:Attach(parent)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if not info then
self:error("You cannot detach tablet with an unregistered parent frame.")
end
if not info.detachedData then
self:error("You cannot attach tablet without a data field.")
end
if info.tooltip and info.tooltip ~= tooltip then
info.tooltip:Attach()
else
info.detachedData.detached = false
end
end
Tablet.Attach = wrap(Tablet.Attach, "Tablet:Attach")
function Tablet:IsAttached(parent)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if not info then
self:error("You cannot check tablet with an unregistered parent frame.")
end
return not info.detachedData or not info.detachedData.detached
end
Tablet.IsAttached = wrap(Tablet.IsAttached, "Tablet:IsAttached")
function Tablet:Refresh(parent)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if not info then
self:error("You cannot refresh tablet with an unregistered parent frame.")
end
local tt = info.tooltip
if tt and not tt.preventRefresh and tt:IsShown() then
tt.updating = true
tt:children()
tt.updating = false
end
end
Tablet.Refresh = wrap(Tablet.Refresh, "Tablet:Refresh")
function Tablet:IsLocked(parent)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if not info then
self:error("You cannot check tablet with an unregistered parent frame.")
end
return info.detachedData and info.detachedData.locked
end
Tablet.IsLocked = wrap(Tablet.IsLocked, "Tablet:IsLocked")
function Tablet:ToggleLocked(parent)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if not info then
self:error("You cannot lock tablet with an unregistered parent frame.")
end
if info.tooltip and info.tooltip ~= tooltip then
info.tooltip:Lock()
elseif info.detachedData then
info.detachedData.locked = info.detachedData.locked
end
end
Tablet.ToggleLocked = wrap(Tablet.ToggleLocked, "Tablet:ToggleLocked")
function Tablet:UpdateDetachedData(parent, detachedData)
self:argCheck(parent, 2, "table", "string")
local info = self.registry[parent]
if not info then
self:error("You cannot update tablet with an unregistered parent frame.")
end
self:argCheck(detachedData, 3, "table")
if info.data == info.detachedData then
info.data = detachedData
end
info.detachedData = detachedData
if info.detachedData.detached then
self:Detach(parent)
elseif info.tooltip and info.tooltip.owner then
self:Attach(parent)
end
end
Tablet.UpdateDetachedData = wrap(Tablet.UpdateDetachedData, "Tablet:UpdateDetachedData")
if DEBUG then
function Tablet:ListProfileInfo()
local duration, times, memories = GetProfileInfo()
self:assert(duration and times and memories)
local t = new()
for method in pairs(memories) do
table.insert(t, method)
end
table.sort(t, function(alpha, bravo)
if memories[alpha] ~= memories[bravo] then
return memories[alpha] < memories[bravo]
elseif times[alpha] ~= times[bravo] then
return times[alpha] < times[bravo]
else
return alpha < bravo
end
end)
local memory = 0
local time = 0
for _,method in ipairs(t) do
DEFAULT_CHAT_FRAME:AddMessage(format("%s || %.3f s || %.3f%% || %d KiB", method, times[method], times[method] / duration * 100, memories[method]))
memory = memory + memories[method]
time = time + times[method]
end
DEFAULT_CHAT_FRAME:AddMessage(format("%s || %.3f s || %.3f%% || %d KiB", "Total", time, time / duration * 100, memory))
del(t)
end
SLASH_TABLET1 = "/tablet"
SLASH_TABLET2 = "/tabletlib"
SlashCmdList["TABLET"] = function(msg)
TabletLib:GetInstance(MAJOR_VERSION):ListProfileInfo()
end
end
local function activate(self, oldLib, oldDeactivate)
Tablet = self
if oldLib then
self.registry = oldLib.registry
self.onceRegistered = oldLib.onceRegistered
self.tooltip = oldLib.tooltip
else
self.registry = {}
self.onceRegistered = {}
end
tooltip = self.tooltip
if oldDeactivate then
oldDeactivate(oldLib)
end
end
local function deactivate(self)
StopCheckingAlt()
end
AceLibrary:Register(Tablet, MAJOR_VERSION, MINOR_VERSION, activate, deactivate)