Files
coa-atlasloot/AtlasLootFu/Libs/Tablet-2.0/Tablet-2.0.lua
T
Andrew6810 db2a2cc2ff init
2022-10-21 06:29:32 -07:00

2974 lines
82 KiB
Lua

--[[
Name: Tablet-2.0
Revision: $Rev: 216 $
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 = 90000 + tonumber(("$Revision: 216 $"):match("(%d+)"))
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"
elseif GetLocale() == "ruRU" 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+перетаскивание для перетаскивания когда планшет зафиксирован."
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
tree[#tree+1] = name
treeMemories[#treeMemories+1] = 0
treeTimes[#treeTimes+1] = 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 function GetMainFrame()
if UIParent:IsShown() then
return UIParent
end
local f = GetUIPanel("fullscreen")
if f and f:IsShown() then
return f
end
return nil
end
GetMainFrame = wrap(GetMainFrame, "GetMainFrame")
local MIN_TOOLTIP_SIZE = 200
local TESTSTRING_EXTRA_WIDTH = 8
local Tablet = {}
local Dewdrop = nil
local CleanCategoryPool
local pool = {}
local function del(t)
setmetatable(t, nil)
for k in pairs(t) do
t[k] = nil
end
t[''] = true
t[''] = nil
pool[t] = true
return nil
end
local function copy(parent)
local t = next(pool)
if not t then
t = {}
else
pool[t] = nil
end
if parent then
for k,v in pairs(parent) do
t[k] = v
end
setmetatable(t, getmetatable(parent))
end
return t
end
local function new(...)
local t = next(pool)
if not t then
t = {}
else
pool[t] = 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
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 = select(2,GameTooltipHeaderText:GetFont())
else
headerSize = 14
end
if GameTooltipText then
normalSize = select(2,GameTooltipText:GetFont())
else
normalSize = 12
end
local tooltip
local testString
local TabletData = {}
local Category = {}
local Line = {}
local function getTestWidth(font, size, text)
if not testString then
return MIN_TOOLTIP_SIZE + 40
end
testString:SetWidth(0)
testString:SetFontObject(font)
local a,_,b = font:GetFont()
testString:SetFont(a, size, b)
testString:SetText(text)
return testString:GetStringWidth()-- + TESTSTRING_EXTRA_WIDTH
end
getTestWidth = wrap(getTestWidth, "getTestWidth")
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 = nil
self.titleR, self.titleG, self.titleB = nil, nil, nil
self.num_lines = 0
setmetatable(self, TabletData_mt)
return self
end
TabletData.new = wrap(TabletData.new, "TabletData:new")
function TabletData:checkMinWidth()
local min = self.minWidth or MIN_TOOLTIP_SIZE
local width = (min - 20)*self.tablet.fontSizePercent
if self.width < width then
self.width = width
end
end
TabletData.checkMinWidth = wrap(TabletData.checkMinWidth, "TabletData:checkMinWidth")
function TabletData:del()
for k, v in ipairs(self.categories) do
v:del()
end
del(self.categories)
del(self)
end
TabletData.del = wrap(TabletData.del, "TabletData:del")
function TabletData:Display()
if self.title and (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.columns - 1)*20
for i = 1, v.columns do
width = width + v['x' .. i]
end
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
TabletData.Display = wrap(TabletData.Display, "TabletData:Display")
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
self.categories[#self.categories+1] = cat
end
if made then
del(info)
end
return cat
end
TabletData.AddCategory = wrap(TabletData.AddCategory, "TabletData:AddCategory")
function TabletData:SetHint(hint)
self.hint = hint
end
TabletData.SetHint = wrap(TabletData.SetHint, "TabletData:SetHint")
function TabletData:SetTitle(title)
self.title = title or "Title"
end
TabletData.SetTitle = wrap(TabletData.SetTitle, "TabletData:SetTitle")
function TabletData:SetTitleColor(r, g, b)
self.titleR = r
self.titleG = g
self.titleB = b
end
TabletData.SetTitleColor = wrap(TabletData.SetTitleColor, "TabletData:SetTitleColor")
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 k:find("^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
for i = 1, self.columns do
self['x' .. i] = 0
end
setmetatable(self, Category_mt)
self.lastWasTitle = nil
local good = self.text
if not good then
for i = 2, self.columns do
if self['text' .. i] then
good = true
break
end
end
end
if good then
local x = new(
'category', category,
'text', self.text,
'fakeChild', true,
'func', self.func,
'onEnterFunc', self.onEnterFunc,
'onLeaveFunc', self.onLeaveFunc,
'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,
'isTitle', self.isTitle
)
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
i = 1
while true do
local k = 'onEnterArg' .. i
local v = self[k]
if v == nil then
break
end
x[k] = v
i = i + 1
end
i = 1
while true do
local k = 'onLeaveArg' .. 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
for i = 2, self.columns do
x['text' .. i] = self['text' .. i]
x['text' .. i .. 'R'] = self['text' .. i .. 'R'] or self['textR' .. i] or 1
x['text' .. i .. 'G'] = self['text' .. i .. 'G'] or self['textG' .. i] or 1
x['text' .. i .. 'B'] = self['text' .. i .. 'B'] or self['textB' .. i] or 1
x['font' .. i] = self['font' .. i]
x['size' .. i] = self['size' .. i]
x['justify' .. i] = self['justify' .. i]
end
if self.checkIcon and self.checkIcon:find("^Interface\\Icons\\") then
x.checkCoordLeft = self.checkCoordLeft or 0.05
x.checkCoordRight = self.checkCoordRight or 0.95
x.checkCoordTop = self.checkCoordTop or 0.05
x.checkCoordBottom = self.checkCoordBottom or 0.95
else
x.checkCoordLeft = self.checkCoordLeft or 0
x.checkCoordRight = self.checkCoordRight or 1
x.checkCoordTop = self.checkCoordTop or 0
x.checkCoordBottom = self.checkCoordBottom or 1
end
x.checkColorR = self.checkColorR or 1
x.checkColorG = self.checkColorG or 1
x.checkColorB = self.checkColorB or 1
self:AddLine(x)
del(x)
self.lastWasTitle = true
end
return self
end
Category.new = wrap(Category.new, "Category:new")
function Category:del()
local prev = garbageLine
for k, v in pairs(self.lines) do
v:del()
end
del(self.lines)
del(self)
end
Category.del = wrap(Category.del, "Category:del")
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
Category.AddLine = wrap(Category.AddLine, "Category:AddLine")
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)
self.lines[#self.lines+1] = cat
if info ~= k1 then
info = del(info)
end
return cat
end
Category.AddCategory = wrap(Category.AddCategory, "Category:AddCategory")
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
Category.HasChildren = wrap(Category.HasChildren, "Category:HasChildren")
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,
'noInherit', 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
Category.Display = wrap(Category.Display, "Category:Display")
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 k:find("^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
category.lines[#category.lines+1] = self
end
setmetatable(self, Line_mt)
local n = category.tabletData.num_lines + 1
category.tabletData.num_lines = n
if n == 10 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
else
for i = 2, columns-1 do
if not self['justify' .. i] then
self['justify' .. i] = "CENTER"
end
end
if not self.justify then
self.justify = "LEFT"
end
if not self['justify' .. columns] then
self['justify' .. columns] = "RIGHT"
end
if self.wrap then
for i = 2, columns do
self['wrap' .. i] = false
end
else
for i = 2, columns do
if self['wrap' .. i] then
for j = i+1, columns do
self['wrap' .. i] = false
end
break
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
for i = 2, columns do
if not self['font' .. i] then
self['font' .. i] = self.font
end
end
if not self.size then
self.size = select(2,self.font:GetFont())
end
for i = 2, columns do
if not self['size' .. i] then
self['size' .. i] = select(2,self['font' .. i]:GetFont())
end
end
if self.checkIcon and self.checkIcon:find("^Interface\\Icons\\") then
if not self.checkCoordLeft then
self.checkCoordLeft = 0.05
end
if not self.checkCoordRight then
self.checkCoordRight = 0.95
end
if not self.checkCoordTop then
self.checkCoordTop = 0.05
end
if not self.checkCoordBottom then
self.checkCoordBottom = 0.95
end
else
if not self.checkCoordLeft then
self.checkCoordLeft = 0
end
if not self.checkCoordRight then
self.checkCoordRight = 1
end
if not self.checkCoordTop then
self.checkCoordTop = 0
end
if not self.checkCoordBottom then
self.checkCoordBottom = 1
end
end
if not self.checkColorR then
self.checkColorR = 1
end
if not self.checkColorG then
self.checkColorG = 1
end
if not self.checkColorB then
self.checkColorB = 1
end
local fontSizePercent = category.tabletData.tablet.fontSizePercent
local w = 0
self.checkWidth = 0
testString = category.tabletData.tablet.buttons[1].col1
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
for i = 3, columns do
local text = self['text' .. i]
if text then
local x_i = 'x' .. i
if not self['wrap' .. i] then
local testWidth = getTestWidth(self['font' .. i], self['size' .. i] * fontSizePercent, text)
local w = testWidth
if category.superCategory[x_i] < w then
category.superCategory[x_i] = w
end
else
local w = MIN_TOOLTIP_SIZE / 2
if category.superCategory[x_i] < w then
category.superCategory[x_i] = w
end
end
end
end
end
return self
end
Line.new = wrap(Line.new, "Line:new")
function Line:del()
del(self)
end
Line.del = wrap(Line.del, "Line:del")
function Line:Display(tablet)
tablet:AddLine(self)
return true
end
Line.Display = wrap(Line.Display, "Line:Display")
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
fake_ipairs = wrap(fake_ipairs, "fake_ipairs")
end
local function argunpack(t, key, i)
if not i then
i = 1
end
local k = key .. i
local v = t[k]
if v then
return v, argunpack(t, key, i+1)
end
end
argunpack = wrap(argunpack, "argunpack")
local delstring, newstring
do
local cache = {}
function delstring(t)
cache[#cache+1] = t
t:SetText(nil)
t:ClearAllPoints()
t:Hide()
t:SetParent(UIParent)
return nil
end
delstring = wrap(delstring, "delstring")
function newstring(parent)
if #cache ~= 0 then
local t = cache[#cache]
cache[#cache] = nil
t:Show()
t:SetParent(parent)
return t
end
local t = parent:CreateFontString(nil, "ARTWORK")
return t
end
newstring = wrap(newstring, "newstring")
end
local function button_OnEnter(this, ...)
if type(this.self:GetScript("OnEnter")) == "function" then
this.self:GetScript("OnEnter")(this.self, ...)
end
this.highlight:Show()
if this.onEnterFunc then
local success, ret = pcall(this.onEnterFunc, argunpack(this, 'onEnterArg'))
if not success then
geterrorhandler()(ret)
end
end
end
button_OnEnter = wrap(button_OnEnter, "button_OnEnter")
local function button_OnLeave(this, ...)
if type(this.self:GetScript("OnLeave")) == "function" then
this.self:GetScript("OnLeave")(this.self, ...)
end
this.highlight:Hide()
if this.onLeaveFunc then
local success, ret = pcall(this.onLeaveFunc, argunpack(this, 'onLeaveArg'))
if not success then
geterrorhandler()(ret)
end
end
end
button_OnLeave = wrap(button_OnLeave, "button_OnLeave")
local lastMouseDown
local function button_OnClick(this, arg1, ...)
if this.self:HasScript("OnClick") and type(this.self:GetScript("OnClick")) == "function" then
this.self:GetScript("OnClick")(this.self, arg1, ...)
end
if arg1 == "RightButton" then
if this.self:HasScript("OnClick") and type(this.self:GetScript("OnClick")) == "function" then
this.self:GetScript("OnClick")(this.self, arg1, ...)
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
local success, ret = pcall(this.func, argunpack(this, 'arg'))
if not success then
geterrorhandler()(ret)
end
if this.self and this.self.registration then
this.self.preventRefresh = false
this.self:children()
this.self.updating = false
end
end
end
end
button_OnClick = wrap(button_OnClick, "button_OnClick")
local function button_OnMouseUp(this, arg1, ...)
if this.self:HasScript("OnMouseUp") and type(this.self:GetScript("OnMouseUp")) == "function" then
this.self:GetScript("OnMouseUp")(this.self, arg1, ...)
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
button_OnMouseUp = wrap(button_OnMouseUp, "button_OnMouseUp")
local function button_OnMouseDown(this, arg1, ...)
if this.self:HasScript("OnMouseDown") and type(this.self:GetScript("OnMouseDown")) == "function" then
this.self:GetScript("OnMouseDown")(this.self, arg1, ...)
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
button_OnMouseDown = wrap(button_OnMouseDown, "button_OnMouseDown")
local function button_OnDragStart(this, ...)
local parent = this:GetParent() and this:GetParent().tablet
if parent:GetScript("OnDragStart") then
return parent:GetScript("OnDragStart")(parent, ...)
end
end
button_OnDragStart = wrap(button_OnDragStart, "button_OnDragStart")
local function button_OnDragStop(this, ...)
local parent = this:GetParent() and this:GetParent().tablet
if parent:GetScript("OnDragStop") then
return parent:GetScript("OnDragStop")(parent, ...)
end
end
button_OnDragStop = wrap(button_OnDragStop, "button_OnDragStop")
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.scrollChild)
button:SetFrameLevel(12)
button.indentation = 0
local check = button:CreateTexture(nil, "ARTWORK")
local col1 = newstring(button)
testString = col1
local highlight = button:CreateTexture(nil, "BACKGROUND")
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
button.highlight = highlight
highlight:SetBlendMode("ADD")
highlight:SetAllPoints(button)
highlight:Hide()
self.buttons[#self.buttons+1] = button
button.check = check
button.col1 = col1
col1:SetWidth(0)
if self.maxLines == 1 then
col1:SetFontObject(GameTooltipHeaderText)
col1:SetJustifyH("CENTER")
button:SetPoint("TOPLEFT", self.scrollFrame, "TOPLEFT", 3, -5)
else
col1: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.scrollFrame, "RIGHT", -7, 0)
check.shown = false
check:SetPoint("TOPLEFT", button, "TOPLEFT")
col1:SetPoint("TOPLEFT", check, "TOPLEFT")
local size = select(2,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()
col1:Hide()
end
end
NewLine = wrap(NewLine, "NewLine")
local function RecalculateTabletHeight(detached)
detached.height_ = nil
if detached.registration and detached.registration.positionFunc then
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 = select(2,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 = select(2,b:GetCenter())
end
if bottom then
bottom = bottom + e
end
end
end
if top and bottom then
detached.height_ = top - bottom
end
end
end
end
RecalculateTabletHeight = wrap(RecalculateTabletHeight, "RecalculateTabletHeight")
local function GetTooltipHeight(self)
RecalculateTabletHeight(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
return height
end
if self.registration.maxHeight then
return self.registration.maxHeight
end
if self == tooltip then
return GetScreenHeight()*3/4
else
return GetScreenHeight()*2/3
end
end
GetTooltipHeight = wrap(GetTooltipHeight, "GetTooltipHeight")
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:SetParent(GetMainFrame())
tooltip:SetFrameStrata(registration.strata or "TOOLTIP")
tooltip:SetFrameLevel(10)
for _,frame in fake_ipairs(tooltip:GetChildren()) do
frame:SetFrameLevel(12)
end
else
tooltip = CreateFrame("Frame", "Tablet20Frame", UIParent)
tooltip:SetParent(GetMainFrame())
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.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:SetScript("OnUpdate", function(this, elapsed)
if not tooltip.updating and (not tooltip.enteredFrame or (overFrame and not MouseIsOver(overFrame))) then
tooltip.scrollFrame:SetVerticalScroll(0)
tooltip.slider:SetValue(0)
tooltip:Hide()
tooltip.registration.tooltip = nil
tooltip.registration = nil
overFrame = nil
end
end)
tooltip:SetScript("OnEnter", function(this)
if tooltip.clickable then
tooltip.enteredFrame = true
overFrame = nil
end
end)
tooltip:SetScript("OnLeave", function(this)
if not tooltip.updating then
tooltip.enteredFrame = false
end
end)
tooltip:SetScript("OnMouseWheel", function(this, arg1)
tooltip.updating = true
tooltip:Scroll(arg1 < 0)
tooltip.updating = false
end)
local scrollFrame = CreateFrame("ScrollFrame", "Tablet20FrameScrollFrame", tooltip)
scrollFrame:SetFrameLevel(11)
local scrollChild = CreateFrame("Frame", "Tablet20FrameScrollChild", scrollFrame)
scrollChild.tablet = tooltip
scrollFrame:SetScrollChild(scrollChild)
tooltip.scrollFrame = scrollFrame
tooltip.scrollChild = scrollChild
scrollFrame:SetPoint("TOPLEFT", 5, -5)
scrollFrame:SetPoint("TOPRIGHT", -5, -5)
scrollFrame:SetPoint("BOTTOMLEFT", 5, 5)
scrollFrame:SetPoint("BOTTOMRIGHT", -5, 5)
scrollChild:SetWidth(1)
scrollChild:SetHeight(1)
local slider = CreateFrame("Slider", "Tablet20FrameSlider", scrollFrame)
tooltip.slider = slider
slider:SetOrientation("VERTICAL")
slider:SetMinMaxValues(0, 1)
slider:SetValueStep(0.001)
slider:SetValue(0)
slider:SetWidth(8)
slider:SetPoint("TOPRIGHT", 0, 0)
slider:SetPoint("BOTTOMRIGHT", 0, 0)
slider:SetBackdrop(new(
'bgFile', "Interface\\Buttons\\UI-SliderBar-Background",
'edgeFile', "Interface\\Buttons\\UI-SliderBar-Border",
'tile', true,
'edgeSize', 8,
'tileSize', 8,
'insets', new(
'left', 3,
'right', 3,
'top', 3,
'bottom', 3
)
))
slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
slider:SetScript("OnEnter", tooltip:GetScript("OnEnter"))
slider:SetScript("OnLeave", tooltip:GetScript("OnLeave"))
slider.tablet = tooltip
slider:SetScript("OnValueChanged", function(this)
local max = this.tablet.scrollChild:GetHeight() - this.tablet:GetHeight()
local val = this:GetValue() * max
if math.abs(this.tablet.scrollFrame:GetVerticalScroll() - val) < 1 then
return
end
this.tablet.scrollFrame:SetVerticalScroll(val)
end)
NewLine(tooltip)
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 = button.check
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.buttons[1].col1
local maxWidth = tabletData and tabletData.width or self:GetWidth() - 20
local hasWrap = false
local numColumns
local height = 20
self:SetWidth(maxWidth + 20)
for i = 1, self.numLines do
local button = self.buttons[i]
local col1 = button.col1
local col2 = button.col2
local check = button.check
button:SetWidth(maxWidth)
button:SetHeight(col2 and math.max(col1:GetHeight(), col2:GetHeight()) or col1:GetHeight())
height = height + button:GetHeight() + 2
if i == 1 then
button:SetPoint("TOPLEFT", self.scrollChild, "TOPLEFT", 5, -5)
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
self.scrollFrame:SetFrameLevel(11)
self.scrollChild:SetWidth(maxWidth)
self.scrollChild:SetHeight(height)
local maxHeight = GetTooltipHeight(self)
if height > maxHeight then
height = maxHeight
self.slider:Show()
else
self.slider:Hide()
end
self:SetHeight(height)
self.scrollFrame:SetScrollChild(self.scrollChild)
local val = self.scrollFrame:GetVerticalScroll()
local max = self.scrollChild:GetHeight() - self:GetHeight()
if val > max then
val = max
end
if val < 0 then
val = 0
end
self.scrollFrame:SetVerticalScroll(val)
self.slider:SetValue(val/max)
end
tooltip.Show = wrap(tooltip.Show, "tooltip:Show")
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 = select(2,info.font:GetFont())
end
local catStart = false
local columns = category and category.columns or 1
local x_total = 0
local x1, x2
if category then
for i = 1, category.columns do
x_total = x_total + category['x' .. i]
end
x1, x2 = category.x1, category.x2
else
x1, x2 = 0, 0
end
self.numLines = self.numLines + 1
NewLine(self)
local num = self.numLines
local button = self.buttons[num]
button:Show()
button.col1:Show()
button.indentation = info.indentation
local col1 = button.col1
local check = button.check
do -- if columns >= 1 then
col1:SetWidth(0)
col1:SetFontObject(info.font)
local font,_,flags = info.font:GetFont()
col1:SetFont(font, info.size * fontSizePercent, flags)
col1:SetText(text)
col1:SetJustifyH(info.justify)
col1:Show()
if info.textR and info.textG and info.textB then
col1:SetTextColor(info.textR, info.textG, info.textB)
else
col1:SetTextColor(1, 0.823529, 0)
end
if columns < 2 then
local i = 2
while true do
local col = button['col' .. i]
if col then
button['col' .. i] = delstring(col)
else
break
end
i = i + 1
end
else
local i = 2
while true do
local col = button['col' .. i]
if not col then
button['col' .. i] = newstring(button)
col = button['col' .. i]
end
col:SetFontObject(info['font' .. i])
col:SetText(info['text' .. i])
col:Show()
local r,g,b = info['text' .. i .. 'R']
if r then
g = info['text' .. i .. 'G']
if g then
b = info['text' .. i .. 'B']
end
end
if b then
col:SetTextColor(r, g, b)
else
col:SetTextColor(1, 0.823529, 0)
end
local a,_,b = info.font2:GetFont()
col:SetFont(a, info['size' .. i] * fontSizePercent, b)
col:SetJustifyH(info['justify' .. i])
if columns == i then
if i == 2 then
col:SetPoint("TOPLEFT", col1, "TOPRIGHT", 40 * fontSizePercent, 0)
col:SetPoint("TOPRIGHT", button, "TOPRIGHT", -5, 0)
else
local col2 = button.col2
col2:ClearAllPoints()
col2:SetPoint("TOPLEFT", col1, "TOPRIGHT", (20 - info.indentation) * fontSizePercent, 0)
end
i = i + 1
while true do
local col = button['col' .. i]
if col then
button['col' .. i] = delstring(col)
else
break
end
i = i + 1
end
break
end
i = i + 1
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
check:SetVertexColor(1, 1, 1)
else
if info.checkIcon then
check:SetTexture(info.checkIcon)
check:SetTexCoord(info.checkCoordLeft, info.checkCoordRight, info.checkCoordTop, info.checkCoordBottom)
check:SetVertexColor(info.checkColorR, info.checkColorG, info.checkColorB)
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)
check:SetVertexColor(1, 1, 1)
end
check:SetAlpha(info.checked and 1 or 0)
end
col1:SetPoint("TOPLEFT", check, "TOPLEFT", check.width, 0)
else
col1:SetPoint("TOPLEFT", check, "TOPLEFT")
end
local col2 = button.col2
if columns == 1 then
col1:SetWidth(maxWidth)
elseif columns == 2 then
if info.wrap then
col1:SetWidth(maxWidth - col2:GetWidth() - 40 * fontSizePercent)
col2:SetWidth(0)
elseif info.wrap2 then
col1:SetWidth(0)
col2:SetWidth(maxWidth - col1:GetWidth() - 40 * fontSizePercent)
else
col1:SetWidth(0)
col2:SetWidth(0)
end
col2:ClearAllPoints()
col2:SetPoint("TOPRIGHT", button, "TOPRIGHT", 0, 0)
if not info.text2 then
col1:SetJustifyH(info.justify or "LEFT")
end
else
col1:SetWidth(x1 - info.checkWidth)
col2:SetWidth(x2)
local num = (category.tabletData.width - x_total) / (columns - 1)
col2:SetPoint("TOPLEFT", col1, "TOPRIGHT", num - info.indentation * fontSizePercent, 0)
local last = col2
for i = 3, category.columns do
local col = button['col' .. i]
col:SetWidth(category['x' .. i])
col:SetPoint("TOPLEFT", last, "TOPRIGHT", num, 0)
last = col
end
end
button.func = nil
button.onEnterFunc = nil
button.onLeaveFunc = nil
button:SetFrameLevel(12) -- hack suggested on forum. Added 06/17/2007. (hC)
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
local k = 'arg' .. i
if button[k] ~= nil then
button[k] = 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[k] = v
i = i + 1
end
local onEnterFunc = info.onEnterFunc
if onEnterFunc then
if type(onEnterFunc) == "string" then
if type(info.onEnterArg1) ~= "table" then
Tablet:error("Cannot call method " .. info.onEnterFunc .. " on a non-table")
end
onEventFunc = info.onEnterArg1[onEnterFunc]
if type(onEnterFunc) ~= "function" then
Tablet:error("Method " .. info.onEnterFunc .. " nonexistant")
end
else
if type(onEnterFunc) ~= "function" then
Tablet:error("func must be a function or method")
end
end
button.onEnterFunc = onEnterFunc
local i = 1
while true do
local k = 'onEnterArg' .. i
if button[k] ~= nil then
button[k] = nil
else
break
end
i = i + 1
end
i = 1
while true do
local k = 'onEnterArg' .. i
local v = info[k]
if v == nil then
break
end
button[k] = v
i = i + 1
end
end
local onLeaveFunc = info.onLeaveFunc
if onLeaveFunc then
if type(onLeaveFunc) == "string" then
if type(info.onLeaveArg1) ~= "table" then
Tablet:error("Cannot call method " .. info.onLeaveFunc .. " on a non-table")
end
onLeaveFunc = info.onLeaveArg1[onLeaveFunc]
if type(onLeaveFunc) ~= "function" then
Tablet:error("Method " .. info.onLeaveFunc .. " nonexistant")
end
else
if type(onLeaveFunc) ~= "function" then
Tablet:error("func must be a function or method")
end
end
button.onLeaveFunc = onLeaveFunc
local i = 1
while true do
local k = 'onLeaveArg' .. i
if button[k] ~= nil then
button[k] = nil
else
break
end
i = i + 1
end
i = 1
while true do
local k = 'onLeaveArg' .. i
local v = info[k]
if v == nil then
break
end
button[k] = v
i = i + 1
end
end
button.self = self
button:SetScript("OnMouseUp", button_OnMouseUp)
button:SetScript("OnMouseDown", button_OnMouseDown)
button:RegisterForDrag("LeftButton")
button:SetScript("OnDragStart", button_OnDragStart)
button:SetScript("OnDragStop", button_OnDragStop)
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:RegisterForDrag()
button:SetScript("OnDragStart", nil)
button:SetScript("OnDragStop", nil)
button:SetScript("OnClick", nil)
button:EnableMouse(false)
end
else
button:SetScript("OnMouseDown", nil)
button:SetScript("OnMouseUp", nil)
button:RegisterForDrag()
button:SetScript("OnDragStart", nil)
button:SetScript("OnDragStop", 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
local ratio = self.fontSizePercent / lastSize
for i = 1, self.numLines do
local button = self.buttons[i]
local j = 1
while true do
local col = button['col' .. j]
if not col then
break
end
local font, size, flags = col:GetFont()
col:SetFont(font, size * ratio, flags)
j = j + 1
end
local check = button.check
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)
self.slider:SetBackdropColor(self.r or 0, self.g or 0, self.b or 0, alpha)
self.slider: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 val
local max = self.scrollChild:GetHeight() - self:GetHeight()
if down then
if IsShiftKeyDown() then
val = max
else
val = self.scrollFrame:GetVerticalScroll() + 36
if val > max then
val = max
end
end
else
if IsShiftKeyDown() then
val = 0
else
val = self.scrollFrame:GetVerticalScroll() - 36
if val < 0 then
val = 0
end
end
end
self.scrollFrame:SetVerticalScroll(val)
self.slider:SetValue(val/max)
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.runChildren = tooltip.runChildren
detached.children = tooltip.children
detached.minWidth = tooltip.minWidth
tooltip.runChildren = nil
tooltip.children = nil
tooltip.minWidth = 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 == "LALT" or modifier == "RALT" then
this.func()
end
end)
end
frame:RegisterEvent("MODIFIER_STATE_CHANGED")
frame.func = func
end
StartCheckingAlt = wrap(StartCheckingAlt, "StartCheckingAlt")
function StopCheckingAlt()
if frame then
frame:UnregisterEvent("MODIFIER_STATE_CHANGED")
end
end
StopCheckingAlt = wrap(StopCheckingAlt, "StopCheckingAlt")
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 GetMainFrame())
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)
RecalculateTabletHeight(detached)
else
detached:SetPoint(detachedData.anchor or "CENTER", GetMainFrame(), 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), GetMainFrame())
detachedTooltips[#detachedTooltips+1] = detached
detached.notInUse = true
detached:EnableMouse(not data.locked)
detached:EnableMouseWheel(true)
detached:SetMovable(true)
detached:SetPoint(data.anchor or "CENTER", GetMainFrame(), 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.transparency = 0.75
detached.r = 0
detached.g = 0
detached.b = 0
detached:SetFrameStrata(registration and 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:EnableMouse(not detached.locked)
local width = GetScreenWidth()
local height = GetScreenHeight()
if registration and registration.movable == false then
detached:RegisterForDrag()
else
detached:RegisterForDrag("LeftButton")
end
detached:SetScript("OnDragStart", function(this)
detached:StartMoving()
detached.moving = true
end)
detached:SetScript("OnDragStop", function(this)
detached:StopMovingOrSizing()
detached.moving = nil
detached:SetClampedToScreen(1)
detached:SetClampedToScreen(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, GetMainFrame(), 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
if type(detached.menu) == "function" then
detached.menu(level, value)
else
Dewdrop:FeedAceOptionsTable(detached.menu)
end
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
if not detached.registration.positionFunc then
Dewdrop:AddLine(
'text', LOCK,
'tooltipTitle', LOCK,
'tooltipText', LOCK_DESC,
'checked', detached:IsLocked(),
'arg1', detached,
'func', "Lock",
'closeWhenClicked', not detached:IsLocked()
)
end
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
local scrollFrame = CreateFrame("ScrollFrame", detached:GetName() .. "ScrollFrame", detached)
local scrollChild = CreateFrame("Frame", detached:GetName() .. "ScrollChild", scrollFrame)
scrollFrame:SetFrameLevel(11)
scrollFrame:SetScrollChild(scrollChild)
scrollChild.tablet = detached
detached.scrollFrame = scrollFrame
detached.scrollChild = scrollChild
scrollFrame:SetPoint("TOPLEFT", 5, -5)
scrollFrame:SetPoint("BOTTOMRIGHT", -5, 5)
scrollChild:SetWidth(1)
scrollChild:SetHeight(1)
local slider = CreateFrame("Slider", detached:GetName() .. "Slider", scrollFrame)
detached.slider = slider
slider:SetOrientation("VERTICAL")
slider:SetMinMaxValues(0, 1)
slider:SetValueStep(0.001)
slider:SetValue(0)
slider:SetWidth(8)
slider:SetPoint("TOPRIGHT", 0, 0)
slider:SetPoint("BOTTOMRIGHT", 0, 0)
slider:SetBackdrop(new(
'bgFile', "Interface\\Buttons\\UI-SliderBar-Background",
'edgeFile', "Interface\\Buttons\\UI-SliderBar-Border",
'tile', true,
'edgeSize', 8,
'tileSize', 8,
'insets', new(
'left', 3,
'right', 3,
'top', 3,
'bottom', 3
)
))
slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
slider:SetScript("OnEnter", detached:GetScript("OnEnter"))
slider:SetScript("OnLeave", detached:GetScript("OnLeave"))
slider.tablet = detached
slider:SetScript("OnValueChanged", Tablet20FrameSlider:GetScript("OnValueChanged"))
NewLine(detached)
detached:SetScript("OnMouseWheel", function(this, arg1)
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
if self.detachedData then
self.detachedData.locked = self.locked or nil
end
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 and tooltip.data == data then
tooltip:Hide()
if tooltip.registration then
tooltip.registration.tooltip = nil
tooltip.registration = nil
end
end
if tooltip then tooltip.enteredFrame = false end
end
Tablet.Close = wrap(Tablet.Close, "Tablet:Close")
local function frame_children(self)
if not self.preventRefresh and self:GetParent() and self:GetParent():IsShown() then
Tablet.currentFrame = self
Tablet.currentTabletData = TabletData:new(self)
Tablet.currentTabletData.minWidth = self.minWidth
self:ClearLines()
if self.runChildren then
self.runChildren()
end
Tablet.currentTabletData:Display(Tablet.currentFrame)
self:Show(Tablet.currentTabletData)
Tablet.currentTabletData:del()
Tablet.currentTabletData = nil
Tablet.currentFrame = nil
end
end
frame_children = wrap(frame_children, "frame_children")
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
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
frame.runChildren = info.children
frame.minWidth = info.minWidth
if not frame.children or not frame.childrenVer or frame.childrenVer < MINOR_VERSION then
frame.childrenVer = MINOR_VERSION
frame.children = frame_children
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
frame:SetClampedToScreen(1)
frame:SetClampedToScreen(nil)
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 new()
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 depth = 0
local categoryPool = {}
function CleanCategoryPool(self)
for k,v in pairs(categoryPool) do
del(v)
categoryPool[k] = nil
end
_id = 0
end
CleanCategoryPool = wrap(CleanCategoryPool, "CleanCategoryPool")
function Tablet:AddCategory(...)
if not self.currentFrame then
self:error("You must add categories in within a registration.")
end
local info = new(...)
local cat = self.currentTabletData:AddCategory(info)
info = del(info)
return cat
end
Tablet.AddCategory = wrap(Tablet.AddCategory, "Tablet:AddCategory")
function Tablet:SetHint(text)
if not self.currentFrame then
self:error("You must set hint within a registration.")
end
self.currentTabletData:SetHint(text)
end
Tablet.SetHint = wrap(Tablet.SetHint, "Tablet:SetHint")
function Tablet:SetTitle(text)
if not self.currentFrame then
self:error("You must set title within a registration.")
end
self.currentTabletData:SetTitle(text)
end
Tablet.SetTitle = wrap(Tablet.SetTitle, "Tablet:SetTitle")
function Tablet:SetTitleColor(r, g, b)
if not self.currentFrame then
self:error("You must set title color within a registration.")
end
self:argCheck(r, 2, "number")
self:argCheck(g, 3, "number")
self:argCheck(b, 4, "number")
self.currentTabletData:SetTitleColor(r, g, b)
end
Tablet.SetTitleColor = wrap(Tablet.SetTitleColor, "Tablet:SetTitleColor")
function Tablet:GetNormalFontSize()
return normalSize
end
Tablet.GetNormalFontSize = wrap(Tablet.GetNormalFontSize, "Tablet:GetNormalFontSize")
function Tablet:GetHeaderFontSize()
return headerSize
end
Tablet.GetHeaderFontSize = wrap(Tablet.GetHeaderFontSize, "Tablet:GetHeaderFontSize")
function Tablet:GetNormalFontObject()
return GameTooltipText
end
Tablet.GetNormalFontObject = wrap(Tablet.GetNormalFontObject, "Tablet:GetNormalFontObject")
function Tablet:GetHeaderFontObject()
return GameTooltipHeaderText
end
Tablet.GetHeaderFontObject = wrap(Tablet.GetHeaderFontObject, "Tablet:GetHeaderFontObject")
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 and tooltip.registration then
tooltip:Detach()
else
info.detachedData.detached = true
local detached = AcquireDetachedFrame(self, info, info.data, info.detachedData)
detached.menu = info.menu
detached.runChildren = info.children
detached.minWidth = info.minWidth
if not detached.children or not detached.childrenVer or detached.childrenVer < MINOR_VERSION then
detached.childrenVer = MINOR_VERSION
detached.children = frame_children
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()
if not duration or not time or not memories then
self:error("Problems")
end
local t = new()
for method in pairs(memories) do
t[#t+1] = 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)
AceLibrary(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
self.currentFrame = oldLib.currentFrame
self.currentTabletData = oldLib.currentTabletData
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)