mirror of
https://github.com/parnic/RepairBroker.git
synced 2025-06-16 09:40:12 -05:00
Sonomus: Initial commit.
git-svn-id: https://repos.wowace.com/wow/repairbroker/trunk@2 25fea357-c8a7-4792-97eb-cca2a7ef4644
This commit is contained in:
6
.pkgmeta
Normal file
6
.pkgmeta
Normal file
@ -0,0 +1,6 @@
|
||||
package-as: RepairBroker
|
||||
|
||||
externals:
|
||||
libs/LibTooltip-1.0: svn://svn.wowace.com/wow/libtooltip/mainline/trunk/LibTooltip-1.0
|
||||
libs/CallbackHandler-1.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/CallbackHandler-1.0
|
||||
libs/LibStub: svn://svn.wowace.com/wow/libstub/mainline/tags/1.0
|
1
ReadMe.txt
Normal file
1
ReadMe.txt
Normal file
@ -0,0 +1 @@
|
||||
Project page: http://www.wowace.com/projects/repairbroker/
|
208
RepairBroker.lua
Normal file
208
RepairBroker.lua
Normal file
@ -0,0 +1,208 @@
|
||||
local LibTooltip = LibStub('LibTooltip-1.0')
|
||||
local LibDataBroker = LibStub('LibDataBroker-1.1')
|
||||
if not LibDataBroker then return end
|
||||
|
||||
local name = "RepairBroker"
|
||||
local Repair = LibDataBroker:NewDataObject(name, {
|
||||
icon = "Interface\\Icons\\Trade_BlackSmithing",
|
||||
label = "Dur",
|
||||
text = "100%",
|
||||
}
|
||||
)
|
||||
|
||||
local print = function(msg) print("|cFF5555AA"..name..": |cFFAAAAFF"..msg) end
|
||||
|
||||
local slots = { }
|
||||
do
|
||||
local slotNames = { "HeadSlot", "ShoulderSlot", "ChestSlot", "WristSlot", "HandsSlot", "WaistSlot", "LegsSlot", "FeetSlot", "MainHandSlot", "SecondaryHandSlot", "RangedSlot" }
|
||||
for i,name in ipairs(slotNames) do
|
||||
slots[ i ] = { GetInventorySlotInfo(name), string.sub(name, 1, string.len(name)-4), 1 }
|
||||
end
|
||||
slotNames = nil -- dispose
|
||||
end
|
||||
|
||||
local OnLoad = function()
|
||||
if not RepairBrokerDB then
|
||||
RepairBrokerDB = {
|
||||
autoRepair = 1, -- nil or 1
|
||||
useBuildBank = nil, -- nil or 1
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------
|
||||
-- Support functions
|
||||
---------------------------------
|
||||
local DurabilityColor = function(perc)
|
||||
if not perc or perc < 0 then return "|cFF555555" end
|
||||
if perc == 1 then
|
||||
return "|cFF005500" -- Dark green
|
||||
elseif perc >= .9 then
|
||||
return "|cFF00AA00" -- Green
|
||||
elseif perc > .5 then
|
||||
return "|cFFFFFF00" -- Yellow
|
||||
elseif perc > .2 then
|
||||
return "|cFFFF9900" -- Orange
|
||||
else
|
||||
return "|cFFFF0000" -- Red
|
||||
end
|
||||
end
|
||||
|
||||
local CopperToString = function(c)
|
||||
local str = ""
|
||||
if not c or c < 0 then return str end
|
||||
if c > 10000 then
|
||||
local g = math.floor(c/10000)
|
||||
c = c - g*10000
|
||||
str = str.."|cFFFFD800"..g.." |TInterface\\MoneyFrame\\UI-GoldIcon.blp:0:0:0:0|t "
|
||||
end
|
||||
if c > 100 then
|
||||
local s = math.floor(c/100)
|
||||
c = c - s*100
|
||||
str = str.."|cFFC7C7C7"..s.." |TInterface\\MoneyFrame\\UI-SilverIcon.blp:0:0:0:0|t "
|
||||
end
|
||||
if c > 0 then
|
||||
str = str.."|cFFEEA55F"..c.." |TInterface\\MoneyFrame\\UI-CopperIcon.blp:0:0:0:0|t "
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
---------------------------------
|
||||
-- Durability updates and repair
|
||||
---------------------------------
|
||||
local UpdateDurability = function()
|
||||
local dur, max
|
||||
local minDur = 1
|
||||
for i,info in ipairs(slots) do
|
||||
if GetInventoryItemLink("player", info[1]) then
|
||||
dur, max = GetInventoryItemDurability(info[1])
|
||||
if not dur or max == 0 then
|
||||
info[3] = -1
|
||||
else
|
||||
info[3] = dur/max
|
||||
if info[3] < minDur then minDur = info[3] end
|
||||
end
|
||||
else
|
||||
info[3] = -1
|
||||
end
|
||||
end
|
||||
Repair.text = DurabilityColor(minDur)..math.floor(minDur*100).."%"
|
||||
end
|
||||
|
||||
local AutoRepair = function()
|
||||
if not RepairBrokerDB.autoRepair then return end
|
||||
local cost, canRepair = GetRepairAllCost()
|
||||
if not canRepair or cost == 0 then return end
|
||||
|
||||
-- Use guildbank to repair
|
||||
if CanWithdrawGuildBankMoney() and RepairBrokerDB.useBuildBank and GetGuildBankMoney() >= cost then
|
||||
RepairAllItems(1)
|
||||
elseif GetMoney() >= cost then -- Repair the old fashion way
|
||||
RepairAllItems()
|
||||
print("Repaired for "..CopperToString(cost))
|
||||
else
|
||||
print("Unable to AutoRepair, you need "..CopperToString(cost - GetMoney()).." more.")
|
||||
end
|
||||
end
|
||||
|
||||
local OnEvent = function(_, event, ...)
|
||||
if event ~= "MERCHANT_SHOW" then
|
||||
UpdateDurability()
|
||||
else
|
||||
AutoRepair()
|
||||
end
|
||||
end
|
||||
|
||||
local event = CreateFrame("Frame")
|
||||
event:RegisterEvent("ADDON_LOADED")
|
||||
event:SetScript("OnEvent", function(_, _, addon)
|
||||
if addon ~= name then return end
|
||||
OnLoad()
|
||||
event:SetScript("OnEvent", OnEvent)
|
||||
event:UnregisterEvent("ADDON_LOADED")
|
||||
event:RegisterEvent("PLAYER_DEAD")
|
||||
event:RegisterEvent("PLAYER_UNGHOST")
|
||||
event:RegisterEvent("PLAYER_REGEN_ENABLED")
|
||||
event:RegisterEvent("UPDATE_INVENTORY_ALERTS")
|
||||
event:RegisterEvent("MERCHANT_SHOW")
|
||||
event:RegisterEvent("MERCHANT_CLOSED")
|
||||
end)
|
||||
|
||||
---------------------------------
|
||||
-- TOOLTIP
|
||||
---------------------------------
|
||||
local tooltip = nil
|
||||
|
||||
function Repair:OnEnter()
|
||||
if tooltip then Repair:OnLeave() end
|
||||
UpdateDurability()
|
||||
tooltip = LibTooltip:Acquire("RepairTooltip", 3, "LEFT", "CENTER", "RIGHT")
|
||||
tooltip:AddHeader("Equipted items")
|
||||
local dur, totalCost, cost = 0, 0, nil
|
||||
local gray = "|cFFAAAAAA"
|
||||
for i,info in ipairs(slots) do
|
||||
dur = math.floor(info[3]*100)
|
||||
if dur >= 0 then
|
||||
dur = DurabilityColor(info[3])..dur
|
||||
dur = dur.."%"
|
||||
else
|
||||
dur = DurabilityColor(-1).."- "
|
||||
end
|
||||
|
||||
cost = select(3, GameTooltip:SetInventoryItem("player", info[1]))
|
||||
tooltip:AddLine(
|
||||
gray..info[2], -- Slot
|
||||
dur, -- Dur
|
||||
CopperToString(cost) -- Cost
|
||||
)
|
||||
if cost and cost > 0 then totalCost = totalCost + cost end
|
||||
end
|
||||
|
||||
local cost, dur, maxDur = 0, 1, 1
|
||||
for bag = 0, 4 do
|
||||
for slot = 1, GetContainerNumSlots(bag) do
|
||||
-- Cost
|
||||
local _, repairCost = GameTooltip:SetBagItem(bag, slot)
|
||||
if repairCost then cost = cost + repairCost end
|
||||
|
||||
-- Dur
|
||||
d, m = GetContainerItemDurability(bag, slot)
|
||||
if d and m then dur = dur + d; maxDur = maxDur + m end
|
||||
end
|
||||
end
|
||||
GameTooltip:Hide()
|
||||
local averageDur = dur/maxDur
|
||||
tooltip:AddHeader(" ")
|
||||
tooltip:AddHeader("Inventory")
|
||||
tooltip:AddLine(
|
||||
gray.."Items in your bags", -- Slot
|
||||
DurabilityColor(averageDur)..math.floor(100*averageDur).."%", -- Dur
|
||||
CopperToString(cost) -- Cost
|
||||
)
|
||||
if cost and cost > 0 then totalCost = totalCost + cost end
|
||||
|
||||
if totalCost > 0 then
|
||||
tooltip:AddHeader(" ")
|
||||
tooltip:AddHeader("Total cost")
|
||||
|
||||
local m = 1
|
||||
for i=4, 8 do
|
||||
tooltip:AddLine(
|
||||
gray.._G["FACTION_STANDING_LABEL"..i], -- Slot
|
||||
" ", -- Dur
|
||||
CopperToString(math.floor(totalCost*m+.5)) -- Cost
|
||||
)
|
||||
m = m - .05
|
||||
end
|
||||
end
|
||||
|
||||
tooltip:SmartAnchorTo(self)
|
||||
tooltip:Show()
|
||||
end
|
||||
|
||||
function Repair:OnLeave()
|
||||
if not tooltip then return end
|
||||
tooltip:Clear()
|
||||
LibTooltip:Release(tooltip)
|
||||
tooltip = nil
|
||||
end
|
13
RepairBroker.toc
Normal file
13
RepairBroker.toc
Normal file
@ -0,0 +1,13 @@
|
||||
## Interface: 30000
|
||||
## Title: Repair Broker
|
||||
## Notes: Auto repair + shows durability.
|
||||
## Author: Merl @ chainwet.net
|
||||
## Version: @project-version@
|
||||
## DefaultState: enabled
|
||||
## SavedVariables: RepairBrokerDB
|
||||
|
||||
libs\LibStub\LibStub.lua
|
||||
libs\CallbackHandler-1.0\CallbackHandler-1.0.lua
|
||||
libs\LibDataBroker-1.1\LibDataBroker-1.1.lua
|
||||
libs\LibTooltip-1.0\LibTooltip-1.0.lua
|
||||
RepairBroker.lua
|
239
libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
Normal file
239
libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
Normal file
@ -0,0 +1,239 @@
|
||||
--[[ $Id: CallbackHandler-1.0.lua 60697 2008-02-09 16:51:20Z nevcairiel $ ]]
|
||||
local MAJOR, MINOR = "CallbackHandler-1.0", 3
|
||||
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
|
||||
|
||||
if not CallbackHandler then return end -- No upgrade needed
|
||||
|
||||
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
|
||||
|
||||
local type = type
|
||||
local pcall = pcall
|
||||
local pairs = pairs
|
||||
local assert = assert
|
||||
local concat = table.concat
|
||||
local loadstring = loadstring
|
||||
local next = next
|
||||
local select = select
|
||||
local type = type
|
||||
local xpcall = xpcall
|
||||
|
||||
local function errorhandler(err)
|
||||
return geterrorhandler()(err)
|
||||
end
|
||||
|
||||
local function CreateDispatcher(argCount)
|
||||
local code = [[
|
||||
local next, xpcall, eh = ...
|
||||
|
||||
local method, ARGS
|
||||
local function call() method(ARGS) end
|
||||
|
||||
local function dispatch(handlers, ...)
|
||||
local index
|
||||
index, method = next(handlers)
|
||||
if not method then return end
|
||||
local OLD_ARGS = ARGS
|
||||
ARGS = ...
|
||||
repeat
|
||||
xpcall(call, eh)
|
||||
index, method = next(handlers, index)
|
||||
until not method
|
||||
ARGS = OLD_ARGS
|
||||
end
|
||||
|
||||
return dispatch
|
||||
]]
|
||||
|
||||
local ARGS, OLD_ARGS = {}, {}
|
||||
for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
|
||||
code = code:gsub("OLD_ARGS", concat(OLD_ARGS, ", ")):gsub("ARGS", concat(ARGS, ", "))
|
||||
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
|
||||
end
|
||||
|
||||
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
|
||||
local dispatcher = CreateDispatcher(argCount)
|
||||
rawset(self, argCount, dispatcher)
|
||||
return dispatcher
|
||||
end})
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- CallbackHandler:New
|
||||
--
|
||||
-- target - target object to embed public APIs in
|
||||
-- RegisterName - name of the callback registration API, default "RegisterCallback"
|
||||
-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
|
||||
-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
|
||||
|
||||
function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
|
||||
-- TODO: Remove this after beta has gone out
|
||||
assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
|
||||
|
||||
RegisterName = RegisterName or "RegisterCallback"
|
||||
UnregisterName = UnregisterName or "UnregisterCallback"
|
||||
if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
|
||||
UnregisterAllName = "UnregisterAllCallbacks"
|
||||
end
|
||||
|
||||
-- we declare all objects and exported APIs inside this closure to quickly gain access
|
||||
-- to e.g. function names, the "target" parameter, etc
|
||||
|
||||
|
||||
-- Create the registry object
|
||||
local events = setmetatable({}, meta)
|
||||
local registry = { recurse=0, events=events }
|
||||
|
||||
-- registry:Fire() - fires the given event/message into the registry
|
||||
function registry:Fire(eventname, ...)
|
||||
if not rawget(events, eventname) or not next(events[eventname]) then return end
|
||||
local oldrecurse = registry.recurse
|
||||
registry.recurse = oldrecurse + 1
|
||||
|
||||
Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
|
||||
|
||||
registry.recurse = oldrecurse
|
||||
|
||||
if registry.insertQueue and oldrecurse==0 then
|
||||
-- Something in one of our callbacks wanted to register more callbacks; they got queued
|
||||
for eventname,callbacks in pairs(registry.insertQueue) do
|
||||
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
|
||||
for self,func in pairs(callbacks) do
|
||||
events[eventname][self] = func
|
||||
-- fire OnUsed callback?
|
||||
if first and registry.OnUsed then
|
||||
registry.OnUsed(registry, target, eventname)
|
||||
first = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
registry.insertQueue = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Registration of a callback, handles:
|
||||
-- self["method"], leads to self["method"](self, ...)
|
||||
-- self with function ref, leads to functionref(...)
|
||||
-- "addonId" (instead of self) with function ref, leads to functionref(...)
|
||||
-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
|
||||
target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
|
||||
if type(eventname) ~= "string" then
|
||||
error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
|
||||
end
|
||||
|
||||
method = method or eventname
|
||||
|
||||
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
|
||||
|
||||
if type(method) ~= "string" and type(method) ~= "function" then
|
||||
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
|
||||
end
|
||||
|
||||
local regfunc
|
||||
|
||||
if type(method) == "string" then
|
||||
-- self["method"] calling style
|
||||
if type(self) ~= "table" then
|
||||
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
|
||||
elseif self==target then
|
||||
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
|
||||
elseif type(self[method]) ~= "function" then
|
||||
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
|
||||
end
|
||||
|
||||
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
|
||||
local arg=select(1,...)
|
||||
regfunc = function(...) self[method](self,arg,...) end
|
||||
else
|
||||
regfunc = function(...) self[method](self,...) end
|
||||
end
|
||||
else
|
||||
-- function ref with self=object or self="addonId"
|
||||
if type(self)~="table" and type(self)~="string" then
|
||||
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string expected.", 2)
|
||||
end
|
||||
|
||||
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
|
||||
local arg=select(1,...)
|
||||
regfunc = function(...) method(arg,...) end
|
||||
else
|
||||
regfunc = method
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if events[eventname][self] or registry.recurse<1 then
|
||||
-- if registry.recurse<1 then
|
||||
-- we're overwriting an existing entry, or not currently recursing. just set it.
|
||||
events[eventname][self] = regfunc
|
||||
-- fire OnUsed callback?
|
||||
if registry.OnUsed and first then
|
||||
registry.OnUsed(registry, target, eventname)
|
||||
end
|
||||
else
|
||||
-- we're currently processing a callback in this registry, so delay the registration of this new entry!
|
||||
-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
|
||||
registry.insertQueue = registry.insertQueue or setmetatable({},meta)
|
||||
registry.insertQueue[eventname][self] = regfunc
|
||||
end
|
||||
end
|
||||
|
||||
-- Unregister a callback
|
||||
target[UnregisterName] = function(self, eventname)
|
||||
if not self or self==target then
|
||||
error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
|
||||
end
|
||||
if type(eventname) ~= "string" then
|
||||
error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
|
||||
end
|
||||
if rawget(events, eventname) and events[eventname][self] then
|
||||
events[eventname][self] = nil
|
||||
-- Fire OnUnused callback?
|
||||
if registry.OnUnused and not next(events[eventname]) then
|
||||
registry.OnUnused(registry, target, eventname)
|
||||
end
|
||||
end
|
||||
if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
|
||||
registry.insertQueue[eventname][self] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
|
||||
if UnregisterAllName then
|
||||
target[UnregisterAllName] = function(...)
|
||||
if select("#",...)<1 then
|
||||
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
|
||||
end
|
||||
if select("#",...)==1 and ...==target then
|
||||
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
|
||||
end
|
||||
|
||||
|
||||
for i=1,select("#",...) do
|
||||
local self = select(i,...)
|
||||
if registry.insertQueue then
|
||||
for eventname, callbacks in pairs(registry.insertQueue) do
|
||||
if callbacks[self] then
|
||||
callbacks[self] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
for eventname, callbacks in pairs(events) do
|
||||
if callbacks[self] then
|
||||
callbacks[self] = nil
|
||||
-- Fire OnUnused callback?
|
||||
if registry.OnUnused and not next(callbacks) then
|
||||
registry.OnUnused(registry, target, eventname)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return registry
|
||||
end
|
||||
|
||||
|
||||
-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
|
||||
-- try to upgrade old implicit embeds since the system is selfcontained and
|
||||
-- relies on closures to work.
|
||||
|
4
libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
Normal file
4
libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="CallbackHandler-1.0.lua"/>
|
||||
</Ui>
|
66
libs/LibDataBroker-1.1/LibDataBroker-1.1.lua
Normal file
66
libs/LibDataBroker-1.1/LibDataBroker-1.1.lua
Normal file
@ -0,0 +1,66 @@
|
||||
|
||||
assert(LibStub, "LibDataBroker-1.1 requires LibStub")
|
||||
assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
|
||||
|
||||
local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 3)
|
||||
if not lib then return end
|
||||
oldminor = oldminor or 0
|
||||
|
||||
|
||||
lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
|
||||
lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
|
||||
local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
|
||||
|
||||
if oldminor < 2 then
|
||||
lib.domt = {
|
||||
__metatable = "access denied",
|
||||
__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
|
||||
}
|
||||
end
|
||||
|
||||
if oldminor < 3 then
|
||||
lib.domt.__newindex = function(self, key, value)
|
||||
if not attributestorage[self] then attributestorage[self] = {} end
|
||||
if attributestorage[self][key] == value then return end
|
||||
attributestorage[self][key] = value
|
||||
local name = namestorage[self]
|
||||
if not name then return end
|
||||
callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
|
||||
callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
|
||||
callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
|
||||
callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
|
||||
end
|
||||
end
|
||||
|
||||
if oldminor < 2 then
|
||||
function lib:NewDataObject(name, dataobj)
|
||||
if self.proxystorage[name] then return end
|
||||
|
||||
if dataobj then
|
||||
assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
|
||||
self.attributestorage[dataobj] = {}
|
||||
for i,v in pairs(dataobj) do
|
||||
self.attributestorage[dataobj][i] = v
|
||||
dataobj[i] = nil
|
||||
end
|
||||
end
|
||||
dataobj = setmetatable(dataobj or {}, self.domt)
|
||||
self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
|
||||
self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
|
||||
return dataobj
|
||||
end
|
||||
end
|
||||
|
||||
if oldminor < 1 then
|
||||
function lib:DataObjectIterator()
|
||||
return pairs(self.proxystorage)
|
||||
end
|
||||
|
||||
function lib:GetDataObjectByName(dataobjectname)
|
||||
return self.proxystorage[dataobjectname]
|
||||
end
|
||||
|
||||
function lib:GetNameByDataObject(dataobject)
|
||||
return self.namestorage[dataobject]
|
||||
end
|
||||
end
|
30
libs/LibStub/LibStub.lua
Normal file
30
libs/LibStub/LibStub.lua
Normal file
@ -0,0 +1,30 @@
|
||||
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
|
||||
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
|
||||
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
|
||||
local LibStub = _G[LIBSTUB_MAJOR]
|
||||
|
||||
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
|
||||
LibStub = LibStub or {libs = {}, minors = {} }
|
||||
_G[LIBSTUB_MAJOR] = LibStub
|
||||
LibStub.minor = LIBSTUB_MINOR
|
||||
|
||||
function LibStub:NewLibrary(major, minor)
|
||||
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
|
||||
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
|
||||
|
||||
local oldminor = self.minors[major]
|
||||
if oldminor and oldminor >= minor then return nil end
|
||||
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
|
||||
return self.libs[major], oldminor
|
||||
end
|
||||
|
||||
function LibStub:GetLibrary(major, silent)
|
||||
if not self.libs[major] and not silent then
|
||||
error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
|
||||
end
|
||||
return self.libs[major], self.minors[major]
|
||||
end
|
||||
|
||||
function LibStub:IterateLibraries() return pairs(self.libs) end
|
||||
setmetatable(LibStub, { __call = LibStub.GetLibrary })
|
||||
end
|
9
libs/LibStub/LibStub.toc
Normal file
9
libs/LibStub/LibStub.toc
Normal file
@ -0,0 +1,9 @@
|
||||
## Interface: 20100
|
||||
## Title: Lib: LibStub
|
||||
## Notes: Universal Library Stub
|
||||
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
|
||||
## X-Website: http://jira.wowace.com/browse/LS | http://www.wowace.com/wiki/LibStub
|
||||
## X-Category: Library
|
||||
## X-License: Public Domain
|
||||
|
||||
LibStub.lua
|
616
libs/LibTooltip-1.0/LibTooltip-1.0.lua
Normal file
616
libs/LibTooltip-1.0/LibTooltip-1.0.lua
Normal file
@ -0,0 +1,616 @@
|
||||
--[[
|
||||
Copyright (c) 2008, LibTooltip Development Team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Redistribution of a stand alone version is strictly prohibited without
|
||||
prior written authorization from the Lead of the LibTooltip Development Team.
|
||||
* Neither the name of the LibTooltip Development Team nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
--]]
|
||||
|
||||
assert(LibStub, "LibTooltip-1.0 requires LibStub")
|
||||
local MAJOR, MINOR = "LibTooltip-1.0", 2
|
||||
local LibTooltip, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
|
||||
if not LibTooltip then return end -- No upgrade needed
|
||||
|
||||
-- Internal constants to tweak the layout
|
||||
local TOOLTIP_PADDING = 10
|
||||
local CELL_MARGIN = 3
|
||||
|
||||
local bgFrame = {
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||||
tile = true,
|
||||
tileSize = 16,
|
||||
edgeSize = 16,
|
||||
insets = {left = 5, right = 5, top = 5, bottom = 5}
|
||||
}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Tables and locals
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
LibTooltip.frameMetatable = LibTooltip.frameMetatable or {__index = CreateFrame("Frame")}
|
||||
|
||||
LibTooltip.tipPrototype = LibTooltip.tipPrototype or setmetatable({}, LibTooltip.frameMetatable)
|
||||
LibTooltip.tipMetatable = LibTooltip.tipMetatable or {__index = LibTooltip.tipPrototype}
|
||||
|
||||
LibTooltip.providerPrototype = LibTooltip.providerPrototype or {}
|
||||
LibTooltip.providerMetatable = LibTooltip.providerMetatable or {__index = LibTooltip.providerPrototype}
|
||||
|
||||
LibTooltip.cellPrototype = LibTooltip.cellPrototype or setmetatable({}, LibTooltip.frameMetatable)
|
||||
LibTooltip.cellMetatable = LibTooltip.cellMetatable or { __index = LibTooltip.cellPrototype }
|
||||
|
||||
LibTooltip.activeTooltips = LibTooltip.activeTooltips or {}
|
||||
LibTooltip.tooltipHeap = LibTooltip.tooltipHeap or {}
|
||||
|
||||
LibTooltip.frameHeap = LibTooltip.frameHeap or {}
|
||||
|
||||
local tipPrototype = LibTooltip.tipPrototype
|
||||
local tipMetatable = LibTooltip.tipMetatable
|
||||
|
||||
local providerPrototype = LibTooltip.providerPrototype
|
||||
local providerMetatable = LibTooltip.providerMetatable
|
||||
|
||||
local cellPrototype = LibTooltip.cellPrototype
|
||||
local cellMetatable = LibTooltip.cellMetatable
|
||||
|
||||
local activeTooltips = LibTooltip.activeTooltips
|
||||
local tooltipHeap = LibTooltip.tooltipHeap
|
||||
|
||||
local frameHeap = LibTooltip.frameHeap
|
||||
|
||||
-- Tooltip private methods
|
||||
local InitializeTooltip, FinalizeTooltip, ResetTooltipSize, ResizeColspans
|
||||
local AcquireCell, ReleaseCell
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Public library API
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
function LibTooltip:Acquire(key, ...)
|
||||
if key == nil then
|
||||
error("attempt to use a nil key", 2)
|
||||
end
|
||||
local tooltip = activeTooltips[key]
|
||||
if not tooltip then
|
||||
tooltip = tremove(tooltipHeap) or setmetatable(CreateFrame("Frame", nil, UIParent), tipMetatable)
|
||||
InitializeTooltip(tooltip, key)
|
||||
activeTooltips[key] = tooltip
|
||||
end
|
||||
if select('#', ...) > 0 then
|
||||
-- Here we catch any error to properly report it for the calling code
|
||||
local ok, msg = pcall(tooltip.SetColumnLayout, tooltip, ...)
|
||||
if not ok then error(msg, 2) end
|
||||
end
|
||||
return tooltip
|
||||
end
|
||||
|
||||
function LibTooltip:IsAcquired(key)
|
||||
if key == nil then
|
||||
error("attempt to use a nil key", 2)
|
||||
end
|
||||
return not not activeTooltips[key]
|
||||
end
|
||||
|
||||
function LibTooltip:Release(tooltip)
|
||||
local key = tooltip and tooltip.key
|
||||
if not key or activeTooltips[key] ~= tooltip then return end
|
||||
tooltip:Hide()
|
||||
FinalizeTooltip(tooltip)
|
||||
tinsert(tooltipHeap, tooltip)
|
||||
activeTooltips[key] = nil
|
||||
end
|
||||
|
||||
function LibTooltip:IterateTooltips()
|
||||
return pairs(activeTooltips)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Frame heap
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local function AcquireFrame(parent)
|
||||
local frame = tremove(frameHeap) or CreateFrame("Frame")
|
||||
frame:SetParent(parent)
|
||||
return frame
|
||||
end
|
||||
|
||||
local function ReleaseFrame(frame)
|
||||
frame:Hide()
|
||||
frame:SetParent(nil)
|
||||
frame:ClearAllPoints()
|
||||
tinsert(frameHeap, frame)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- CellProvider and Cell
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- Provider prototype
|
||||
|
||||
function providerPrototype:AcquireCell(tooltip)
|
||||
local cell = tremove(self.heap)
|
||||
if not cell then
|
||||
cell = setmetatable(CreateFrame("Frame", nil, tooltip), self.cellMetatable)
|
||||
if type(cell.InitializeCell) == 'function' then
|
||||
cell:InitializeCell()
|
||||
end
|
||||
end
|
||||
self.cells[cell] = true
|
||||
return cell
|
||||
end
|
||||
|
||||
function providerPrototype:ReleaseCell(cell)
|
||||
if not self.cells[cell] then return end
|
||||
if type(cell.ReleaseCell) == 'function' then
|
||||
cell:ReleaseCell()
|
||||
end
|
||||
self.cells[cell] = nil
|
||||
tinsert(self.heap, cell)
|
||||
end
|
||||
|
||||
function providerPrototype:GetCellPrototype()
|
||||
return self.cellPrototype, self.cellMetatable
|
||||
end
|
||||
|
||||
function providerPrototype:IterateCells()
|
||||
return pairs(self.cells)
|
||||
end
|
||||
|
||||
-- Cell provider factory
|
||||
|
||||
function LibTooltip:CreateCellProvider(baseProvider)
|
||||
local cellBaseMetatable, cellBasePrototype
|
||||
if baseProvider and baseProvider.GetCellPrototype then
|
||||
cellBasePrototype, cellBaseMetatable = baseProvider:GetCellPrototype()
|
||||
else
|
||||
cellBaseMetatable = cellMetatable
|
||||
end
|
||||
local cellPrototype = setmetatable({}, cellBaseMetatable)
|
||||
local cellProvider = setmetatable({}, providerMetatable)
|
||||
cellProvider.heap = {}
|
||||
cellProvider.cells = {}
|
||||
cellProvider.cellPrototype = cellPrototype
|
||||
cellProvider.cellMetatable = { __index = cellPrototype }
|
||||
return cellProvider, cellPrototype, cellBasePrototype
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Basic label provider
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
if not LibTooltip.LabelProvider then
|
||||
LibTooltip.LabelProvider, LibTooltip.LabelPrototype = LibTooltip:CreateCellProvider()
|
||||
end
|
||||
|
||||
local labelProvider = LibTooltip.LabelProvider
|
||||
local labelPrototype = LibTooltip.LabelPrototype
|
||||
|
||||
function labelPrototype:InitializeCell()
|
||||
self.fontString = self:CreateFontString()
|
||||
self.fontString:SetAllPoints(self)
|
||||
self.fontString:SetFontObject(GameTooltipText)
|
||||
end
|
||||
|
||||
function labelPrototype:SetupCell(tooltip, value, justification, font, ...)
|
||||
local fs = self.fontString
|
||||
fs:SetFontObject(font or tooltip:GetFont())
|
||||
fs:SetJustifyH(justification)
|
||||
fs:SetText(tostring(value))
|
||||
fs:Show()
|
||||
return fs:GetStringWidth(), fs:GetStringHeight()
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Helpers
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local function checkFont(font, level, silent)
|
||||
if not font or type(font) ~= 'table' or type(font.IsObjectType) ~= 'function' or not font:IsObjectType("Font") then
|
||||
if silent then
|
||||
return false
|
||||
else
|
||||
error("font must be Font instance, not: "..tostring(font), level+1)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function checkJustification(justification, level, silent)
|
||||
if justification ~= "LEFT" and justification ~= "CENTER" and justification ~= "RIGHT" then
|
||||
if silent then
|
||||
return false
|
||||
else
|
||||
error("invalid justification, must one of LEFT, CENTER or RIGHT, not: "..tostring(justification), level+1)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Tooltip prototype
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
function InitializeTooltip(self, key)
|
||||
-- (Re)set frame settings
|
||||
self:SetBackdrop(bgFrame)
|
||||
self:SetBackdropColor(0.09, 0.09, 0.09)
|
||||
self:SetBackdropBorderColor(1, 1, 1)
|
||||
self:SetAlpha(0.9)
|
||||
self:SetScale(1.0)
|
||||
self:SetFrameStrata("TOOLTIP")
|
||||
self:SetClampedToScreen(false)
|
||||
|
||||
-- Our data
|
||||
self.key = key
|
||||
self.columns = self.columns or {}
|
||||
self.lines = self.lines or {}
|
||||
self.colspans = self.colspans or {}
|
||||
|
||||
self.regularFont = GameTooltipText
|
||||
self.headerFont = GameTooltipHeaderText
|
||||
|
||||
self:SetScript('OnShow', ResizeColspans)
|
||||
|
||||
ResetTooltipSize(self)
|
||||
end
|
||||
|
||||
function tipPrototype:SetColumnLayout(numColumns, ...)
|
||||
if type(numColumns) ~= "number" or numColumns < 1 then
|
||||
error("number of columns must be a positive number, not: "..tostring(numColumns), 2)
|
||||
end
|
||||
for i = 1, numColumns do
|
||||
local justification = select(i, ...) or "LEFT"
|
||||
checkJustification(justification, 2)
|
||||
if self.columns[i] then
|
||||
self.columns[i].justification = justification
|
||||
else
|
||||
self:AddColumn(justification)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function tipPrototype:AddColumn(justification)
|
||||
justification = justification or "LEFT"
|
||||
checkJustification(justification, 2)
|
||||
local colNum = #self.columns + 1
|
||||
local column = AcquireFrame(self)
|
||||
column.justification = justification
|
||||
column.width = 0
|
||||
column:SetWidth(0)
|
||||
column:SetPoint("TOP", self, "TOP", 0, -TOOLTIP_PADDING)
|
||||
column:SetPoint("BOTTOM", self, "BOTTOM", 0, TOOLTIP_PADDING)
|
||||
if colNum > 1 then
|
||||
column:SetPoint("LEFT", self.columns[colNum-1], "RIGHT", CELL_MARGIN, 0)
|
||||
self.width = self.width + CELL_MARGIN
|
||||
self:SetWidth(self.width)
|
||||
else
|
||||
column:SetPoint("LEFT", self, "LEFT", TOOLTIP_PADDING, 0)
|
||||
end
|
||||
column:Show()
|
||||
self.columns[colNum] = column
|
||||
return colNum
|
||||
end
|
||||
|
||||
function FinalizeTooltip(self)
|
||||
self:Clear()
|
||||
for i, column in ipairs(self.columns) do
|
||||
column:Hide()
|
||||
ReleaseFrame(column)
|
||||
self.columns[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function ResetTooltipSize(self)
|
||||
self.width = 2*TOOLTIP_PADDING + math.max(0, CELL_MARGIN * (#self.columns - 1))
|
||||
self.height = 2*TOOLTIP_PADDING
|
||||
self:SetWidth(self.width)
|
||||
self:SetHeight(self.height)
|
||||
end
|
||||
|
||||
function tipPrototype:Clear()
|
||||
for i, line in ipairs(self.lines) do
|
||||
for j, cell in ipairs(line.cells) do
|
||||
ReleaseCell(self, cell)
|
||||
line.cells[j] = nil
|
||||
end
|
||||
line:Hide()
|
||||
ReleaseFrame(line)
|
||||
self.lines[i] = nil
|
||||
end
|
||||
for i, column in ipairs(self.columns) do
|
||||
column.width = 0
|
||||
column:SetWidth(0)
|
||||
end
|
||||
for k in pairs(self.colspans) do
|
||||
self.colspans[k] = nil
|
||||
end
|
||||
ResetTooltipSize(self)
|
||||
end
|
||||
|
||||
function tipPrototype:SetFont(font)
|
||||
checkFont(font, 2)
|
||||
self.regularFont = font
|
||||
end
|
||||
|
||||
function tipPrototype:GetFont() return self.regularFont end
|
||||
|
||||
function tipPrototype:SetHeaderFont(font)
|
||||
checkFont(font, 2)
|
||||
self.headerFont = font
|
||||
end
|
||||
|
||||
function tipPrototype:GetHeaderFont() return self.headerFont end
|
||||
|
||||
local function EnlargeColumn(self, column, width)
|
||||
if width > column.width then
|
||||
self.width = self.width + width - column.width
|
||||
self:SetWidth(self.width)
|
||||
column.width = width
|
||||
column:SetWidth(width)
|
||||
end
|
||||
end
|
||||
|
||||
function ResizeColspans(self)
|
||||
if not self:IsShown() then return end
|
||||
local columns = self.columns
|
||||
for colRange, width in pairs(self.colspans) do
|
||||
local left, right = colRange:match("(%d)%-(%d)")
|
||||
left, right = tonumber(left), tonumber(right)
|
||||
for col = left, right-1 do
|
||||
width = width - columns[col].width - CELL_MARGIN
|
||||
end
|
||||
EnlargeColumn(self, columns[right], width)
|
||||
self.colspans[colRange] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function AcquireCell(self, provider)
|
||||
local cell = provider:AcquireCell(self)
|
||||
cell:SetParent(self)
|
||||
cell:SetFrameLevel(self:GetFrameLevel()+1)
|
||||
return cell
|
||||
end
|
||||
|
||||
function ReleaseCell(self, cell)
|
||||
if cell and cell:GetParent() == self then
|
||||
cell:Hide()
|
||||
cell:SetParent(nil)
|
||||
cell:ClearAllPoints()
|
||||
cell._provider:ReleaseCell(cell)
|
||||
end
|
||||
end
|
||||
|
||||
local function _SetCell(self, lineNum, colNum, value, font, justification, colSpan, provider, ...)
|
||||
local line = self.lines[lineNum]
|
||||
local cells = line.cells
|
||||
|
||||
-- Unset: be quick
|
||||
if value == nil then
|
||||
local cell = cells[colNum]
|
||||
if cell then
|
||||
for i = colNum, colNum + cell._colSpan - 1 do
|
||||
cells[i] = nil
|
||||
end
|
||||
ReleaseCell(self, cell)
|
||||
end
|
||||
return lineNum, colNum
|
||||
end
|
||||
|
||||
-- Check previous cell
|
||||
local cell
|
||||
local prevCell = cells[colNum]
|
||||
if prevCell == false then
|
||||
error("overlapping cells at column "..colNum, 3)
|
||||
elseif prevCell then
|
||||
-- There is a cell here
|
||||
font = font or prevCell._font
|
||||
justification = justification or prevCell._justification
|
||||
colSpan = colSpan or prevCell._colSpan
|
||||
if provider == nil or prevCell._provider == provider then
|
||||
-- Reuse existing cell
|
||||
cell = prevCell
|
||||
provider = cell._provider
|
||||
else
|
||||
-- A new cell is required
|
||||
ReleaseCell(self, prevCell)
|
||||
cells[colNum] = nil
|
||||
end
|
||||
else
|
||||
-- Creating a new cell, use meaning full defaults
|
||||
provider = provider or labelProvider
|
||||
font = font or self.regularFont
|
||||
justification = justification or self.columns[colNum].justification or "LEFT"
|
||||
colSpan = colSpan or 1
|
||||
end
|
||||
|
||||
local tooltipWidth = #self.columns
|
||||
local rightColNum
|
||||
if colSpan > 0 then
|
||||
rightColNum = colNum + colSpan - 1
|
||||
if rightColNum > tooltipWidth then
|
||||
error("ColSpan too big, cell extends beyond right-most column", 3)
|
||||
end
|
||||
else
|
||||
-- Zero or negative: count back from right-most columns
|
||||
rightColNum = math.max(colNum, tooltipWidth + colSpan)
|
||||
-- Update colspan to its effective value
|
||||
colSpan = 1 + rightColNum - colNum
|
||||
end
|
||||
|
||||
-- Cleanup colspans
|
||||
for i = colNum + 1, rightColNum do
|
||||
local cell = cells[i]
|
||||
if cell == false then
|
||||
error("overlapping cells at column "..i, 3)
|
||||
elseif cell then
|
||||
ReleaseCell(self, cell)
|
||||
end
|
||||
cells[i] = false
|
||||
end
|
||||
|
||||
-- Create the cell and anchor it
|
||||
if not cell then
|
||||
cell = AcquireCell(self, provider)
|
||||
cell:SetPoint("LEFT", self.columns[colNum], "LEFT", 0, 0)
|
||||
cell:SetPoint("TOP", line, "TOP", 0, 0)
|
||||
cell:SetPoint("BOTTOM", line, "BOTTOM", 0, 0)
|
||||
cells[colNum] = cell
|
||||
end
|
||||
cell:SetPoint("RIGHT", self.columns[rightColNum], "RIGHT", 0, 0)
|
||||
|
||||
-- Store the cell settings directly into the cell
|
||||
-- That's a bit risky but is is really cheap compared to other ways to do it
|
||||
cell._provider, cell._font, cell._justification, cell._colSpan = provider, font, justification, colSpan
|
||||
|
||||
-- Setup the cell content
|
||||
local width, height = cell:SetupCell(tooltip, value, justification, font, ...)
|
||||
|
||||
-- Enforce cell size
|
||||
cell:SetWidth(width)
|
||||
cell:SetHeight(height)
|
||||
cell:Show()
|
||||
|
||||
if colSpan > 1 then
|
||||
-- Postpone width changes until the tooltip is shown
|
||||
local colRange = colNum.."-"..rightColNum
|
||||
self.colspans[colRange] = math.max(self.colspans[colRange] or 0, width)
|
||||
else
|
||||
-- Enlarge the column and tooltip if need be
|
||||
EnlargeColumn(self, self.columns[colNum], width)
|
||||
end
|
||||
|
||||
-- Enlarge the line and tooltip if need be
|
||||
if height > line.height then
|
||||
self.height = self.height + height - line.height
|
||||
self:SetHeight(self.height)
|
||||
line.height = height
|
||||
line:SetHeight(height)
|
||||
end
|
||||
|
||||
if rightColNum < tooltipWidth then
|
||||
return lineNum, rightColNum+1
|
||||
else
|
||||
return lineNum, nil
|
||||
end
|
||||
end
|
||||
|
||||
local function CreateLine(self, font, ...)
|
||||
local line = AcquireFrame(self)
|
||||
local lineNum = #self.lines + 1
|
||||
line:SetPoint('LEFT', self, 'LEFT', TOOLTIP_PADDING, 0)
|
||||
line:SetPoint('RIGHT', self, 'RIGHT', -TOOLTIP_PADDING, 0)
|
||||
if lineNum > 1 then
|
||||
line:SetPoint('TOP', self.lines[lineNum-1], 'BOTTOM', 0, -CELL_MARGIN)
|
||||
self.height = self.height + CELL_MARGIN
|
||||
self:SetHeight(self.height)
|
||||
else
|
||||
line:SetPoint('TOP', self, 'TOP', 0, -TOOLTIP_PADDING)
|
||||
end
|
||||
self.lines[lineNum] = line
|
||||
line.cells = line.cells or {}
|
||||
line.height = 0
|
||||
line:SetHeight(0)
|
||||
line:Show()
|
||||
|
||||
local colNum = 1
|
||||
for i = 1, #self.columns do
|
||||
local value = select(i, ...)
|
||||
if value ~= nil then
|
||||
lineNum, colNum = _SetCell(self, lineNum, i, value, font, nil, 1, labelProvider)
|
||||
end
|
||||
end
|
||||
return lineNum, colNum
|
||||
end
|
||||
|
||||
function tipPrototype:AddLine(...)
|
||||
local lineNum, colNum = CreateLine(self, self.regularFont, ...)
|
||||
ResizeColspans(self)
|
||||
return lineNum, colNum
|
||||
end
|
||||
|
||||
function tipPrototype:AddHeader(...)
|
||||
local lineNum, colNum = CreateLine(self, self.headerFont, ...)
|
||||
ResizeColspans(self)
|
||||
return lineNum, colNum
|
||||
end
|
||||
|
||||
function tipPrototype:SetCell(lineNum, colNum, value, ...)
|
||||
-- Mandatory argument checking
|
||||
if type(lineNum) ~= "number" then
|
||||
error("line number must be a number, not: "..tostring(lineNum), 2)
|
||||
elseif lineNum < 1 or lineNum > #self.lines then
|
||||
error("line number out of range: "..tostring(lineNum), 2)
|
||||
elseif type(colNum) ~= "number" then
|
||||
error("column number must be a number, not: "..tostring(colNum), 2)
|
||||
elseif colNum < 1 or colNum > #self.columns then
|
||||
error("column number out of range: "..tostring(colNum), 2)
|
||||
end
|
||||
|
||||
-- Variable argument checking
|
||||
local font, justification, colSpan, provider
|
||||
local i, arg = 1, ...
|
||||
if arg == nil or checkFont(arg, 2, true) then
|
||||
i, font, arg = 2, ...
|
||||
end
|
||||
if arg == nil or checkJustification(arg, 2, true) then
|
||||
i, justification, arg = i+1, select(i, ...)
|
||||
end
|
||||
if arg == nil or type(arg) == 'number' then
|
||||
i, colSpan, arg = i+1, select(i, ...)
|
||||
end
|
||||
if arg == nil or type(arg) == 'table' and type(arg.AcquireCell) == 'function' then
|
||||
i, provider = i+1, arg
|
||||
end
|
||||
|
||||
lineNum, colNum = _SetCell(self, lineNum, colNum, value, font, justification, colSpan, provider, select(i, ...))
|
||||
ResizeColspans(self)
|
||||
return lineNum, colNum
|
||||
end
|
||||
|
||||
function tipPrototype:GetLineCount() return #self.lines end
|
||||
|
||||
function tipPrototype:GetColumnCount() return #self.columns end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- "Smart" Anchoring (work in progress)
|
||||
------------------------------------------------------------------------------
|
||||
local function GetTipAnchor(frame)
|
||||
local x,y = frame:GetCenter()
|
||||
if not x or not y then return "TOPLEFT", "BOTTOMLEFT" end
|
||||
local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or ""
|
||||
local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM"
|
||||
return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf
|
||||
end
|
||||
|
||||
function tipPrototype:SmartAnchorTo(frame)
|
||||
if not frame then
|
||||
error("Invalid frame provided.", 2)
|
||||
end
|
||||
self:ClearAllPoints()
|
||||
self:SetClampedToScreen(true)
|
||||
self:SetPoint(GetTipAnchor(frame))
|
||||
end
|
Reference in New Issue
Block a user