vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | |
2 | local vmajor, vminor = "1", tonumber(string.sub("$Revision: 3764 $", 12, -3)) |
||
3 | local stubvarname = "TekLibStub" |
||
4 | local libvarname = "Gratuity" |
||
5 | |||
6 | |||
7 | -- Check to see if an update is needed |
||
8 | -- if not then just return out now before we do anything |
||
9 | local libobj = getglobal(libvarname) |
||
10 | if libobj and not libobj:NeedsUpgraded(vmajor, vminor) then return end |
||
11 | |||
12 | |||
13 | local stubobj = getglobal(stubvarname) |
||
14 | if not stubobj then |
||
15 | stubobj = {} |
||
16 | setglobal(stubvarname, stubobj) |
||
17 | |||
18 | |||
19 | -- Instance replacement method, replace contents of old with that of new |
||
20 | function stubobj:ReplaceInstance(old, new) |
||
21 | for k,v in pairs(old) do old[k]=nil end |
||
22 | for k,v in pairs(new) do old[k]=v end |
||
23 | end |
||
24 | |||
25 | |||
26 | -- Get a new copy of the stub |
||
27 | function stubobj:NewStub(name) |
||
28 | local newStub = {} |
||
29 | self:ReplaceInstance(newStub, self) |
||
30 | newStub.libName = name |
||
31 | newStub.lastVersion = '' |
||
32 | newStub.versions = {} |
||
33 | return newStub |
||
34 | end |
||
35 | |||
36 | |||
37 | -- Get instance version |
||
38 | function stubobj:NeedsUpgraded(vmajor, vminor) |
||
39 | local versionData = self.versions[vmajor] |
||
40 | if not versionData or versionData.minor < vminor then return true end |
||
41 | end |
||
42 | |||
43 | |||
44 | -- Get instance version |
||
45 | function stubobj:GetInstance(version) |
||
46 | if not version then version = self.lastVersion end |
||
47 | local versionData = self.versions[version] |
||
48 | if not versionData then print(string.format("<%s> Cannot find library version: %s", self.libName, version or "")) return end |
||
49 | return versionData.instance |
||
50 | end |
||
51 | |||
52 | |||
53 | -- Register new instance |
||
54 | function stubobj:Register(newInstance) |
||
55 | local version,minor = newInstance:GetLibraryVersion() |
||
56 | self.lastVersion = version |
||
57 | local versionData = self.versions[version] |
||
58 | if not versionData then |
||
59 | -- This one is new! |
||
60 | versionData = { |
||
61 | instance = newInstance, |
||
62 | minor = minor, |
||
63 | old = {}, |
||
64 | } |
||
65 | self.versions[version] = versionData |
||
66 | newInstance:LibActivate(self) |
||
67 | return newInstance |
||
68 | end |
||
69 | -- This is an update |
||
70 | local oldInstance = versionData.instance |
||
71 | local oldList = versionData.old |
||
72 | versionData.instance = newInstance |
||
73 | versionData.minor = minor |
||
74 | local skipCopy = newInstance:LibActivate(self, oldInstance, oldList) |
||
75 | table.insert(oldList, oldInstance) |
||
76 | if not skipCopy then |
||
77 | for i, old in ipairs(oldList) do self:ReplaceInstance(old, newInstance) end |
||
78 | end |
||
79 | return newInstance |
||
80 | end |
||
81 | end |
||
82 | |||
83 | ---------------------------- |
||
84 | -- Library Code -- |
||
85 | ---------------------------- |
||
86 | if not libobj then |
||
87 | libobj = stubobj:NewStub(libvarname) |
||
88 | setglobal(libvarname, libobj) |
||
89 | end |
||
90 | |||
91 | local lib = {} |
||
92 | |||
93 | |||
94 | -- Return the library's current version |
||
95 | function lib:GetLibraryVersion() |
||
96 | return vmajor, vminor |
||
97 | end |
||
98 | |||
99 | local methods = { |
||
100 | "SetBagItem", "SetAction", "SetAuctionItem", "SetAuctionSellItem", "SetBuybackItem", |
||
101 | "SetCraftItem", "SetCraftSpell", "SetHyperlink", "SetInboxItem", "SetInventoryItem", |
||
102 | "SetLootItem", "SetLootRollItem", "SetMerchantItem", "SetPetAction", "SetPlayerBuff", |
||
103 | "SetQuestItem", "SetQuestLogItem", "SetQuestRewardSpell", "SetSendMailItem", "SetShapeshift", |
||
104 | "SetSpell", "SetTalent", "SetTrackingSpell", "SetTradePlayerItem", "SetTradeSkillItem", "SetTradeTargetItem", |
||
105 | "SetTrainerService", "SetUnit", "SetUnitBuff", "SetUnitDebuff", |
||
106 | } |
||
107 | |||
108 | local function err(message) |
||
109 | local stack = debugstack() |
||
110 | local first = string.gsub(stack, "\n.*", "") |
||
111 | local file = string.gsub(first, "^(.*\\.*).lua:%d+: .*", "%1") |
||
112 | file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") |
||
113 | if not message then |
||
114 | local _,_,second = string.find(stack, "\n(.-)\n") |
||
115 | message = "An error occured! " .. second |
||
116 | end |
||
117 | message = "Gratuity: " .. message |
||
118 | local i = 1 |
||
119 | for s in string.gfind(stack, "\n([^\n]*)") do |
||
120 | i = i + 1 |
||
121 | if not string.find(s, file .. "%.lua:%d+:") then |
||
122 | error(message, i) |
||
123 | return |
||
124 | end |
||
125 | end |
||
126 | error(message, 2) |
||
127 | end |
||
128 | |||
129 | local function assert(condition, message) |
||
130 | if not condition then |
||
131 | if not message then |
||
132 | local _,_,second = string.find(debugstack(), "\n(.-)\n") |
||
133 | message = "assertion failed! " .. second |
||
134 | end |
||
135 | err(message) |
||
136 | return |
||
137 | end |
||
138 | return condition |
||
139 | end |
||
140 | |||
141 | -- Activate a new instance of this library |
||
142 | function lib:LibActivate(stub, oldLib, oldList) |
||
143 | local maj, min = self:GetLibraryVersion() |
||
144 | |||
145 | if oldLib then |
||
146 | local omaj, omin = oldLib:GetLibraryVersion() |
||
147 | for _,m in pairs(methods) do |
||
148 | self[m] = oldLib[m] |
||
149 | end |
||
150 | self.vars = oldLib.vars |
||
151 | if self.vars.tooltip then self:CreateSetMethods() end |
||
152 | else |
||
153 | self.vars = {} |
||
154 | end |
||
155 | if not self.vars.tooltip then self:CreateTooltip() end |
||
156 | -- nil return makes stub do object copy |
||
157 | end |
||
158 | |||
159 | |||
160 | function lib:InitCompost() |
||
161 | if not self.vars.compost and CompostLib then self.vars.compost = CompostLib:GetInstance("compost-1") end |
||
162 | end |
||
163 | |||
164 | |||
165 | -- Retreive the tooltip assigned to Gratuity |
||
166 | function lib:GetTooltip(tooltip) |
||
167 | return self.vars.tooltip |
||
168 | end |
||
169 | |||
170 | |||
171 | ------------------------------------------------------------------------------------- |
||
172 | -- Pass a tooltip frame to be used (make sure the tooltip does not have a parent!!!) |
||
173 | -- You can use this line in your XML to define the tooltip: |
||
174 | -- <GameTooltip name="NameGoesHere" inherits="GameTooltipTemplate"/> |
||
175 | -- This *would* be part of the EmbedLib but the game throws an error |
||
176 | -- when you try to declare two tooltips with the same name *growl* |
||
177 | ------------------------------------------------------------------------------------- |
||
178 | -- Returns the stored tooltip (this may not match what you passed!) |
||
179 | -- You need to be careful how you use the tooltip or it can |
||
180 | -- get "detached" from it's owner and stop parsing. Please make sure you read up |
||
181 | -- about tips here: http://www.wowwiki.com/UIOBJECT_GameTooltip |
||
182 | ------------------------------------------------------------------------------------- |
||
183 | -- ******************************************************************************* -- |
||
184 | -- ** THIS METHOD IS NOW DEPRICIATED! Patch 1.11 now allows me to dynamically ** -- |
||
185 | -- ** create a viable GameTooltip with pure LUA. ** -- |
||
186 | -- ** Mods no longer need to register a tooltip! ** -- |
||
187 | -- ******************************************************************************* -- |
||
188 | ------------------------------------------------------------------------------------- |
||
189 | function lib:RegisterTooltip(tooltip) |
||
190 | return self.vars.tooltip |
||
191 | end |
||
192 | |||
193 | |||
194 | function lib:CreateTooltip() |
||
195 | local tt = CreateFrame("GameTooltip") |
||
196 | |||
197 | self.vars.tooltip = tt |
||
198 | tt:SetOwner(tt, "ANCHOR_NONE") |
||
199 | -- tooltip:SetParent() |
||
200 | |||
201 | self.vars.Llines, self.vars.Rlines = {}, {} |
||
202 | for i=1,30 do |
||
203 | self.vars.Llines[i] = tt:CreateFontString() |
||
204 | self.vars.Rlines[i] = tt:CreateFontString() |
||
205 | self.vars.Llines[i]:SetFontObject(GameFontNormal) |
||
206 | self.vars.Rlines[i]:SetFontObject(GameFontNormal) |
||
207 | tt:AddFontStrings(self.vars.Llines[i], self.vars.Rlines[i]) |
||
208 | end |
||
209 | |||
210 | if not self.SetBagItem then self:CreateSetMethods() end |
||
211 | |||
212 | return tt |
||
213 | end |
||
214 | |||
215 | |||
216 | -- Clears the tooltip completely, none of this "erase left, hide right" crap blizzard does |
||
217 | -- returns true is successful, nil if no tooltip assigned |
||
218 | function lib:Erase() |
||
219 | assert(self.vars.tooltip, "No tooltip declared!") |
||
220 | |||
221 | self.vars.tooltip:ClearLines() -- Ensures tooltip's NumLines is reset |
||
222 | for i=1,30 do self.vars.Rlines[i]:SetText() end -- Clear text from right side (ClearLines only hides them) |
||
223 | |||
224 | if not self.vars.tooltip:IsVisible() then self.vars.tooltip:SetOwner(self.vars.tooltip, "ANCHOR_NONE") end |
||
225 | |||
226 | return true |
||
227 | end |
||
228 | |||
229 | |||
230 | -- Get the number of lines |
||
231 | -- Arg: endln - If passed and tooltip's NumLines is higher, endln is returned back |
||
232 | function lib:NumLines(endln) |
||
233 | local num = self.vars.tooltip:NumLines() |
||
234 | return endln and num > endln and endln or num or 0 |
||
235 | end |
||
236 | |||
237 | |||
238 | -- If text is found on tooltip then results of string.find are returned |
||
239 | -- Args: |
||
240 | -- txt - The text string to find |
||
241 | -- startln - First tooltip line to check, default 1 |
||
242 | -- endln - Last line to test, default 30 |
||
243 | -- ignoreleft / ignoreright - Causes text on one side of the tooltip to be ignored |
||
244 | function lib:Find(txt, startln, endln, ignoreleft, ignoreright) |
||
245 | assert(txt, "No search string passed") |
||
246 | local t1, t2 = type(startln or 1), type(self:NumLines(endln)) |
||
247 | if (t1 ~= "number" or t2 ~= "number") then print(t1, t2, (startln or 1),self:NumLines(endln)) end |
||
248 | for i=(startln or 1),self:NumLines(endln) do |
||
249 | if not ignoreleft then |
||
250 | local txtl = self.vars.Llines[i]:GetText() |
||
251 | if (txtl and string.find(txtl, txt)) then return string.find(txtl, txt) end |
||
252 | end |
||
253 | |||
254 | if not ignoreright then |
||
255 | local txtr = self.vars.Rlines[i]:GetText() |
||
256 | if (txtr and string.find(txtr, txt)) then return string.find(txtr, txt) end |
||
257 | end |
||
258 | end |
||
259 | end |
||
260 | |||
261 | |||
262 | -- Calls Find many times. |
||
263 | -- Args are passed directly to Find, t1-t10 replace the txt arg |
||
264 | function lib:MultiFind(startln, endln, ignoreleft, ignoreright, t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) |
||
265 | assert(t1, "No search string passed") |
||
266 | if t1 and self:Find(t1, startln, endln, ignoreleft, ignoreright) then return self:Find(t1, startln, endln, ignoreleft, ignoreright) |
||
267 | elseif t2 then return self:MultiFind(startln, endln, ignoreleft, ignoreright, t2,t3,t4,t5,t6,t7,t8,t9,t10) end |
||
268 | end |
||
269 | |||
270 | |||
271 | local deformat |
||
272 | -- If text is found on tooltip then results of deformat:Deformat are returned |
||
273 | -- Args: |
||
274 | -- txt - The text string to deformat and serach for |
||
275 | -- startln - First tooltip line to check, default 1 |
||
276 | -- endln - Last line to test, default 30 |
||
277 | -- ignoreleft / ignoreright - Causes text on one side of the tooltip to be ignored |
||
278 | function lib:FindDeformat(txt, startln, endln, ignoreleft, ignoreright) |
||
279 | assert(txt, "No search string passed") |
||
280 | if not deformat then |
||
281 | assert(BabbleLib, "You must have BabbleLib-Core 1.1 or BabbleLib-Deformat 1.2 available") |
||
282 | if BabbleLib.versions["Deformat 1.2"] then |
||
283 | deformat = BabbleLib:GetInstance("Deformat 1.2") |
||
284 | elseif BabbleLib.versions["Core 1.1"] then |
||
285 | deformat = BabbleLib:GetInstance("Core 1.1") |
||
286 | else |
||
287 | assert(false, "You must have BabbleLib-Core 1.1 or BabbleLib-Deformat 1.2 available") |
||
288 | end |
||
289 | end |
||
290 | |||
291 | for i=(startln or 1),self:NumLines(endln) do |
||
292 | if not ignoreleft then |
||
293 | local txtl = self.vars.Llines[i]:GetText() |
||
294 | if (txtl and deformat:Deformat(txtl, txt)) then return deformat:Deformat(txtl, txt) end |
||
295 | end |
||
296 | |||
297 | if not ignoreright then |
||
298 | local txtr = self.vars.Rlines[i]:GetText() |
||
299 | if (txtr and deformat:Deformat(txtr, txt)) then return deformat:Deformat(txtr, txt) end |
||
300 | end |
||
301 | end |
||
302 | end |
||
303 | |||
304 | |||
305 | -- Returns a table of strings pulled from the tooltip, or nil if no strings in tooltip |
||
306 | -- Args: |
||
307 | -- startln - First tooltip line to check, default 1 |
||
308 | -- endln - Last line to test, default 30 |
||
309 | -- ignoreleft / ignoreright - Causes text on one side of the tooltip to be ignored |
||
310 | function lib:GetText(startln, endln, ignoreleft, ignoreright) |
||
311 | self:InitCompost() |
||
312 | local retval |
||
313 | |||
314 | for i=(startln or 1),(endln or 30) do |
||
315 | local txtl, txtr |
||
316 | if not ignoreleft then txtl = self.vars.Llines[i]:GetText() end |
||
317 | if not ignoreright then txtr = self.vars.Rlines[i]:GetText() end |
||
318 | if txtl or txtr then |
||
319 | if not retval then retval = self.vars.compost and self.vars.compost:Acquire() or {} end |
||
320 | local t = self.vars.compost and self.vars.compost:Acquire(txtl, txtr) or {txtl, txtr} |
||
321 | table.insert(retval, t) |
||
322 | end |
||
323 | end |
||
324 | |||
325 | return retval |
||
326 | end |
||
327 | |||
328 | |||
329 | -- Returns the text from a specific line (both left and right unless second arg is true) |
||
330 | -- Args: |
||
331 | -- line - the line number you wish to retrieve |
||
332 | -- getright - if passed the right line will be returned, if not the left will be returned |
||
333 | function lib:GetLine(line, getright) |
||
334 | assert(type(line) == "number", "No line number passed") |
||
335 | if self.vars.tooltip:NumLines() < line then return end |
||
336 | if getright then return self.vars.Rlines[line] and self.vars.Rlines[line]:GetText() |
||
337 | elseif self.vars.Llines[line] then |
||
338 | return self.vars.Llines[line]:GetText(), self.vars.Rlines[line]:GetText() |
||
339 | end |
||
340 | end |
||
341 | |||
342 | |||
343 | ----------------------------------- |
||
344 | -- Set tooltip methods -- |
||
345 | ----------------------------------- |
||
346 | |||
347 | -- These methods are designed to immitate the GameTooltip API |
||
348 | -- CreateSetMethods is called on RegisterTooltip if not yet defined |
||
349 | |||
350 | local testmethods = { |
||
351 | SetAction = function(id) return HasAction(id) end, |
||
352 | } |
||
353 | local gettrue = function() return true end |
||
354 | function lib:CreateSetMethods() |
||
355 | for _,m in pairs(methods) do |
||
356 | local meth = m |
||
357 | local func = testmethods[meth] or gettrue |
||
358 | lib[meth] = function(self,a1,a2,a3,a4) |
||
359 | self:Erase() |
||
360 | if not func(a1,a2,a3,a4) then return end |
||
361 | local s, r1,r2,r3,r4,r5,r6,r7,r8,r9,r10 = pcall(self.vars.tooltip[meth], self.vars.tooltip,a1,a2,a3,a4) |
||
362 | if s then return r1,r2,r3,r4,r5,r6,r7,r8,r9,r10 |
||
363 | else err(r1) end |
||
364 | end |
||
365 | end |
||
366 | end |
||
367 | |||
368 | |||
369 | -------------------------------- |
||
370 | -- Load this bitch! -- |
||
371 | -------------------------------- |
||
372 | libobj:Register(lib) |