annotate LibFarmbuyer.lua @ 146:543fcf15add7

Handle new itemstring format for item variants. Heroic, warforged, etc, are now additional fields in the itemstring rather than separate item IDs as in the last few expansions. This fixes the tooltip displays for such items; there's nothing yet in place for determining the exact variations (need to finish the list of bonus codes). Some minor efficiency tweaks.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Tue, 30 Dec 2014 17:52:30 -0500
parents fb4bda3ad05c
children
rev   line source
farmbuyer@1 1 --[[
farmbuyer@1 2 Not really meant for public use. Stuff that I keep using everywhere and
farmbuyer@1 3 got tired of reimplementing, or even copy-and-pasting. The notes here are
farmbuyer@1 4 reminders to myself.
farmbuyer@1 5
farmbuyer@1 6 Library contents:
farmbuyer@1 7 - author_debug
farmbuyer@1 8 Evaluates to true if I'm hacking on something.
farmbuyer@1 9
farmbuyer@19 10 - tableprint(t[,f])
farmbuyer@100 11 A single print() call to the tostring'd contents of T, including nils;
farmbuyer@100 12 strings are cleaned up with respect to embedded '|'/control chars. A
farmbuyer@100 13 single space is used during concatenation of T. If a function F is passed,
farmbuyer@100 14 calls that instead of print(). Returns the accumulated string and either
farmbuyer@100 15 T or the returned values of F, depending on which was used.
farmbuyer@1 16
farmbuyer@1 17 - safeprint(...)
farmbuyer@19 18 Same as tableprint() on the argument list. Returns the results of tableprint.
farmbuyer@45 19 Generates some garbage.
farmbuyer@1 20
farmbuyer@1 21 - safeiprint(...)
farmbuyer@19 22 Same as safeprint() but with <index> numbers inserted. Returns the results
farmbuyer@45 23 of tableprint. Generates some garbage.
farmbuyer@19 24 Ex: safeiprint(a,b,c) --> <1>,a,<2>,b,<3>,c
farmbuyer@1 25
farmbuyer@45 26 - safefprint/safefiprint(f,...)
farmbuyer@45 27 Takes a function F as first parameter, for passing to tableprint().
farmbuyer@45 28
farmbuyer@1 29 - t = StaticPopup(t)
farmbuyer@1 30 Fills out "typical" settings inside T, especially if T contains any kind
farmbuyer@1 31 of editbox:
farmbuyer@1 32 + cannot accept an empty editbox
farmbuyer@39 33 + pressing Enter runs OnAccept (also will not accept empty editbox)
farmbuyer@1 34 + editbox grabs keyboard focus
farmbuyer@1 35 + OnAccept runs with editbox's text in dialog.usertext
farmbuyer@1 36 Returns T.
farmbuyer@1 37
farmbuyer@1 38 - nullfunc()
farmbuyer@1 39 Empty placeholder function. Will be less useful if WoW ever moves to Lua 5.2.
farmbuyer@1 40 This is a fascinating and educational place to insert print calls...
farmbuyer@1 41
farmbuyer@1 42 - tabledump(t)/dumptable(t)
farmbuyer@1 43 If author_debug, this runs the builtin /dump command on T. Otherwise nothing.
farmbuyer@1 44
farmbuyer@1 45 - DoOnceNextUpdate(f)
farmbuyer@1 46 Runs F on the next frame refresh cycle. Multiple calls in one cycle will
farmbuyer@1 47 stack LIFO. Calls *while* processing the stack are safe, and will be stacked
farmbuyer@1 48 up for the next cycle.
farmbuyer@6 49
farmbuyer@6 50 - safecall (func, ...)
farmbuyer@6 51 A modified copy of the xpcall wrapper duplicated in every Ace3 file in the
farmbuyer@6 52 whole damn library.
farmbuyer@6 53
farmbuyer@6 54 - new(...), del(t), copy(t), clear()
farmbuyer@6 55 Ditto for table recycling.
farmbuyer@1 56 ]]
farmbuyer@1 57
farmbuyer@122 58 local MAJOR, MINOR = "LibFarmbuyer", 20
farmbuyer@1 59 assert(LibStub,MAJOR.." requires LibStub")
farmbuyer@1 60 local lib = LibStub:NewLibrary(MAJOR, MINOR)
farmbuyer@1 61 if not lib then return end
farmbuyer@1 62
farmbuyer@1 63 _G[MAJOR] = lib
farmbuyer@1 64
farmbuyer@1 65 ----------------------------------------------------------------------
farmbuyer@6 66 --[[
farmbuyer@6 67 Recycling functions yoinked from AceConfigDialog and tweaked
farmbuyer@6 68 ]]
farmbuyer@1 69 local new, del, copy, clear
farmbuyer@6 70 do
farmbuyer@6 71 local pool = setmetatable({},{__mode="k"})
farmbuyer@6 72 function clear()
farmbuyer@6 73 wipe(pool)
farmbuyer@6 74 end
farmbuyer@6 75 function new(...) -- slightly modified variant, takes optional initializers
farmbuyer@6 76 local t = next(pool)
farmbuyer@6 77 if t then
farmbuyer@6 78 pool[t] = nil
farmbuyer@6 79 for i = 1, select('#',...) do
farmbuyer@6 80 t[i] = select(i,...)
farmbuyer@6 81 end
farmbuyer@6 82 return t
farmbuyer@6 83 else
farmbuyer@6 84 return {...}
farmbuyer@6 85 end
farmbuyer@6 86 end
farmbuyer@6 87 function copy(t)
farmbuyer@6 88 local c = new()
farmbuyer@6 89 for k, v in pairs(t) do
farmbuyer@6 90 c[k] = v
farmbuyer@6 91 end
farmbuyer@6 92 return c
farmbuyer@6 93 end
farmbuyer@6 94 function del(t)
farmbuyer@6 95 wipe(t)
farmbuyer@6 96 pool[t] = true
farmbuyer@6 97 end
farmbuyer@6 98 end
farmbuyer@6 99 lib.new, lib.del, lib.copy, lib.clear = new, del, copy, clear
farmbuyer@1 100
farmbuyer@1 101
farmbuyer@1 102 ----------------------------------------------------------------------
farmbuyer@1 103 --[[
farmbuyer@95 104 safeprint and company (primarily for on-the-fly debugging)
farmbuyer@1 105 ]]
farmbuyer@56 106 local tconcat, tostring, tonumber = table.concat, tostring, tonumber
farmbuyer@1 107 local function undocontrol(c)
farmbuyer@1 108 return ("\\%.3d"):format(c:byte())
farmbuyer@1 109 end
farmbuyer@1 110 function lib.safeprint(...)
farmbuyer@1 111 local args = { n=select('#',...), ... }
farmbuyer@19 112 return lib.tableprint(args)
farmbuyer@1 113 end
farmbuyer@45 114 function lib.safefprint(f,...)
farmbuyer@45 115 local args = { n=select('#',...), ... }
farmbuyer@45 116 return lib.tableprint(args,f)
farmbuyer@45 117 end
farmbuyer@1 118 function lib.safeiprint(...)
farmbuyer@1 119 local args = { n=select('#',...), ... }
farmbuyer@1 120 local last = args.n
farmbuyer@1 121 while last > 0 do
farmbuyer@1 122 table.insert (args, last, "<"..last..">")
farmbuyer@1 123 last = last - 1
farmbuyer@1 124 end
farmbuyer@1 125 args.n = 2 * args.n
farmbuyer@19 126 return lib.tableprint(args)
farmbuyer@1 127 end
farmbuyer@45 128 function lib.safefiprint(f,...)
farmbuyer@45 129 local args = { n=select('#',...), ... }
farmbuyer@45 130 local last = args.n
farmbuyer@45 131 while last > 0 do
farmbuyer@45 132 table.insert (args, last, "<"..last..">")
farmbuyer@45 133 last = last - 1
farmbuyer@45 134 end
farmbuyer@45 135 args.n = 2 * args.n
farmbuyer@45 136 return lib.tableprint(args,f)
farmbuyer@45 137 end
farmbuyer@19 138 function lib.tableprint(t,f)
farmbuyer@1 139 for i = 1, (tonumber(t.n) or #t) do
farmbuyer@1 140 t[i] = tostring(t[i]):gsub('\124','\124\124')
farmbuyer@1 141 :gsub('(%c)', undocontrol)
farmbuyer@1 142 end
farmbuyer@56 143 local msg = tconcat(t,' ', 1, tonumber(t.n) or #t)
farmbuyer@45 144 if type(f) == 'function' then
farmbuyer@45 145 return msg,f(msg)
farmbuyer@1 146 else
farmbuyer@19 147 print(msg)
farmbuyer@19 148 return msg,t
farmbuyer@1 149 end
farmbuyer@1 150 end
farmbuyer@1 151
farmbuyer@1 152 -- See below for global versions.
farmbuyer@1 153
farmbuyer@1 154
farmbuyer@1 155 ----------------------------------------------------------------------
farmbuyer@1 156 local StaticPopupDialogs = _G.StaticPopupDialogs
farmbuyer@1 157
farmbuyer@1 158 local function EditBoxOnTextChanged_notempty (editbox) -- this is also called when first shown
farmbuyer@1 159 if editbox:GetText() ~= "" then
farmbuyer@1 160 editbox:GetParent().button1:Enable()
farmbuyer@1 161 else
farmbuyer@1 162 editbox:GetParent().button1:Disable()
farmbuyer@1 163 end
farmbuyer@1 164 end
farmbuyer@1 165 local function EditBoxOnEnterPressed_accept (editbox)
farmbuyer@39 166 if editbox:GetText() == "" then return end
farmbuyer@39 167 local dialog = editbox:GetParent()
farmbuyer@39 168 StaticPopupDialogs[dialog.which].OnAccept (dialog, dialog.data, dialog.data2)
farmbuyer@39 169 dialog:Hide()
farmbuyer@1 170 end
farmbuyer@69 171 local function OnShow_ontop (dialog, data)
farmbuyer@1 172 local info = StaticPopupDialogs[dialog.which]
farmbuyer@69 173 -- ace3's elements are hardcoded to this strata, make sure popups
farmbuyer@69 174 -- can also be seen (their toplevel=true attribute handles the
farmbuyer@69 175 -- framelevels within the same strata)
farmbuyer@69 176 info.saved_strata = dialog:GetFrameStrata()
farmbuyer@69 177 dialog:SetFrameStrata("FULLSCREEN_DIALOG")
farmbuyer@69 178 if info.hasEditBox then
farmbuyer@69 179 dialog.editBox:SetFocus()
farmbuyer@69 180 end
farmbuyer@1 181 if info.farm_OnShow then
farmbuyer@1 182 return info.farm_OnShow (dialog, data)
farmbuyer@1 183 end
farmbuyer@1 184 end
farmbuyer@1 185 local function OnAccept_witheditbox (dialog, data, data2)
farmbuyer@1 186 local info = StaticPopupDialogs[dialog.which]
farmbuyer@16 187 dialog.usertext = dialog.editBox:GetText():trim()
farmbuyer@1 188 if info.farm_OnAccept then
farmbuyer@1 189 return info.farm_OnAccept (dialog, data, data2)
farmbuyer@1 190 end
farmbuyer@1 191 end
farmbuyer@69 192 local function OnHide_cleanup (dialog, data)
farmbuyer@69 193 local info = StaticPopupDialogs[dialog.which]
farmbuyer@69 194 if info.farm_OnHide then
farmbuyer@69 195 return info.farm_OnHide (dialog, data)
farmbuyer@69 196 end
farmbuyer@16 197 dialog.data = nil
farmbuyer@16 198 dialog.data2 = nil
farmbuyer@69 199 dialog:SetFrameStrata(info.saved_strata or "DIALOG")
farmbuyer@16 200 end
farmbuyer@1 201
farmbuyer@1 202 --[[
farmbuyer@1 203 StaticPopup
farmbuyer@1 204 ]]
farmbuyer@1 205 function lib.StaticPopup (t)
farmbuyer@57 206 if t.hasEditBox then
farmbuyer@57 207 t.EditBoxOnTextChanged = EditBoxOnTextChanged_notempty
farmbuyer@57 208 t.EditBoxOnEnterPressed = EditBoxOnEnterPressed_accept
farmbuyer@1 209 if t.OnAccept then
farmbuyer@1 210 t.farm_OnAccept = t.OnAccept
farmbuyer@1 211 end
farmbuyer@57 212 t.OnAccept = OnAccept_witheditbox
farmbuyer@1 213 -- this calls OnCancel with "clicked", unless noCancelOnEscape is set
farmbuyer@57 214 t.EditBoxOnEscapePressed = StaticPopup_EscapePressed
farmbuyer@57 215 end
farmbuyer@1 216
farmbuyer@69 217 t.farm_OnShow = t.OnShow
farmbuyer@69 218 t.OnShow = OnShow_ontop
farmbuyer@69 219 t.farm_OnHide = t.OnHide
farmbuyer@69 220 t.OnHide = OnHide_cleanup
farmbuyer@16 221
farmbuyer@57 222 t.timeout = 0
farmbuyer@57 223 t.whileDead = true
farmbuyer@57 224 t.hideOnEscape = true
farmbuyer@1 225 t.enterClicksFirstButton = true
farmbuyer@53 226 t.preferredIndex = 3 -- http://forums.wowace.com/showthread.php?t=19960
farmbuyer@1 227
farmbuyer@57 228 return t
farmbuyer@1 229 end
farmbuyer@1 230
farmbuyer@1 231
farmbuyer@1 232 ----------------------------------------------------------------------
farmbuyer@1 233 --[[
farmbuyer@1 234 This is ugly, but at least it all gets GC'd almost immediately.
farmbuyer@1 235 ]]
farmbuyer@1 236 function lib.nullfunc() end
farmbuyer@1 237
farmbuyer@1 238 if ({
farmbuyer@1 239 ["Bandwagon"] = true, ["Kilvin"] = true, ["Waterfaucet"] = true,
farmbuyer@1 240 ["Farmbuyer"] = true, ["Oxdeadbeef"] = true, ["Pointystick"] = true,
farmbuyer@1 241 ["Angryhobbit"] = true, ["Malrubius"] = true, ["Hemogoblin"] = true,
farmbuyer@16 242 ["Ossipago"] = true,
farmbuyer@1 243 })[UnitName("player")] then
farmbuyer@1 244 lib.author_debug = true
farmbuyer@1 245 _G.safeprint = lib.safeprint
farmbuyer@1 246 _G.safeiprint = lib.safeiprint
farmbuyer@1 247 function lib.tabledump(t)
farmbuyer@73 248 -- Should instead load this and then call the subcommands directly.
farmbuyer@73 249 --_G.UIParentLoadAddOn("Blizzard_DebugTools")
farmbuyer@1 250 _G.LibF_DEBUG = t
farmbuyer@1 251 _G.SlashCmdList.DUMP("LibF_DEBUG")
farmbuyer@1 252 end
farmbuyer@1 253 else
farmbuyer@92 254 -- make sure earlier lib's members aren't lingering
farmbuyer@92 255 lib.author_debug = nil
farmbuyer@92 256 _G.safeprint = nil
farmbuyer@92 257 _G.safeiprint = nil
farmbuyer@1 258 lib.tabledump = lib.nullfunc
farmbuyer@1 259 end
farmbuyer@1 260 lib.dumptable = lib.tabledump
farmbuyer@1 261
farmbuyer@1 262
farmbuyer@1 263 ----------------------------------------------------------------------
farmbuyer@1 264 --[[
farmbuyer@1 265 DoOnceNextUpdate
farmbuyer@1 266 ]]
farmbuyer@1 267 do
farmbuyer@1 268 local frame = CreateFrame("Frame", "LibFarmbuyerDONUFrame")
farmbuyer@1 269 frame:Hide()
farmbuyer@1 270 frame:SetScript("OnUpdate", function()
farmbuyer@1 271 frame:Hide()
farmbuyer@1 272 local q = frame.nexttime
farmbuyer@1 273 local tmp
farmbuyer@1 274 frame.nexttime = nil
farmbuyer@1 275 while q do
farmbuyer@1 276 tmp = q
farmbuyer@1 277 q.f(frame)
farmbuyer@1 278 q = q.n
farmbuyer@1 279 del(tmp)
farmbuyer@1 280 end
farmbuyer@1 281 end)
farmbuyer@1 282
farmbuyer@1 283 function lib.DoOnceNextUpdate (func)
farmbuyer@1 284 local nextt = new()
farmbuyer@1 285 nextt.f = func
farmbuyer@1 286 nextt.n = frame.nexttime
farmbuyer@1 287 frame.nexttime = nextt
farmbuyer@1 288 frame:Show()
farmbuyer@1 289 end
farmbuyer@1 290 end
farmbuyer@1 291
farmbuyer@1 292
farmbuyer@1 293 ----------------------------------------------------------------------
farmbuyer@6 294 --[[
farmbuyer@6 295 safecall
farmbuyer@6 296 ]]
farmbuyer@1 297 do
farmbuyer@6 298 local xpcall = xpcall
farmbuyer@6 299
farmbuyer@6 300 local function errorhandler(err)
farmbuyer@6 301 --return geterrorhandler()(err)
farmbuyer@6 302 --print("in error handler", err)
farmbuyer@6 303 return err
farmbuyer@1 304 end
farmbuyer@6 305
farmbuyer@6 306 local template = ([[
farmbuyer@6 307 local xpcall, eh = ...
farmbuyer@6 308 local method, ARGS
farmbuyer@6 309 local function call() return method(ARGS) end
farmbuyer@6 310
farmbuyer@6 311 local function dispatch (func, ...)
farmbuyer@6 312 method = func
farmbuyer@6 313 if not method then return end
farmbuyer@6 314 ARGS = ...
farmbuyer@6 315 return xpcall (call, eh)
farmbuyer@1 316 end
farmbuyer@6 317
farmbuyer@6 318 return dispatch
farmbuyer@6 319 ]]):gsub('\t',' ')
farmbuyer@6 320
farmbuyer@6 321 local function CreateDispatcher(argCount)
farmbuyer@6 322 local ARGS = {}
farmbuyer@6 323 for i = 1, argCount do ARGS[i] = "arg"..i end
farmbuyer@19 324 local code = template:gsub("ARGS", tconcat(ARGS, ", "))
farmbuyer@6 325 return assert(loadstring(code, "LibF/safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
farmbuyer@1 326 end
farmbuyer@6 327
farmbuyer@6 328 local Dispatchers = setmetatable({
farmbuyer@6 329 [0] = function(func)
farmbuyer@6 330 return xpcall (func, errorhandler)
farmbuyer@1 331 end
farmbuyer@6 332 }, {
farmbuyer@6 333 __index = function (Ds, argCount)
farmbuyer@6 334 local dispatcher = CreateDispatcher(argCount)
farmbuyer@6 335 Ds[argCount] = dispatcher
farmbuyer@6 336 return dispatcher
farmbuyer@6 337 end
farmbuyer@6 338 })
farmbuyer@6 339
farmbuyer@6 340 function lib.safecall (func, ...)
farmbuyer@6 341 if type(func) == 'function' then
farmbuyer@6 342 return Dispatchers[select('#', ...)](func, ...)
farmbuyer@6 343 end
farmbuyer@1 344 end
farmbuyer@1 345 end
farmbuyer@1 346
farmbuyer@6 347
farmbuyer@6 348 ----------------------------------------------------------------------
farmbuyer@6 349
farmbuyer@1 350 -- vim: noet