view LibFarmbuyer.lua @ 23:8664134bba4f

Add '/ouroloot ping' command, same functionality as button in options panel.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Fri, 09 Sep 2011 00:56:13 +0000
parents f560cf82e7d3
children 8f7ec6ccf5e3
line wrap: on
line source
--[[
Not really meant for public use.  Stuff that I keep using everywhere and
got tired of reimplementing, or even copy-and-pasting.  The notes here are
reminders to myself.

Library contents:
- author_debug
  Evaluates to true if I'm hacking on something.

- tableprint(t[,f])
  A single print() call to the contents of T, including nils; strings are
  cleaned up with respect to embedded '|'/control chars.  If a function F is
  passed, calls that instead of print().  Returns the results of F, or the
  text string passed to print(), depending on which was used.

- safeprint(...)
  Same as tableprint() on the argument list.  Returns the results of tableprint.

- safeiprint(...)
  Same as safeprint() but with <index> numbers inserted.  Returns the results
  of tableprint.
  Ex:  safeiprint(a,b,c)  -->  <1>,a,<2>,b,<3>,c

- t = StaticPopup(t)
  Fills out "typical" settings inside T, especially if T contains any kind
  of editbox:
   + cannot accept an empty editbox
   + pressing Enter runs OnAccept
   + editbox grabs keyboard focus
   + OnAccept runs with editbox's text in dialog.usertext
  Returns T.

- nullfunc()
  Empty placeholder function.  Will be less useful if WoW ever moves to Lua 5.2.
  This is a fascinating and educational place to insert print calls...

- tabledump(t)/dumptable(t)
  If author_debug, this runs the builtin /dump command on T.  Otherwise nothing.

- DoOnceNextUpdate(f)
  Runs F on the next frame refresh cycle.  Multiple calls in one cycle will
  stack LIFO.  Calls *while* processing the stack are safe, and will be stacked
  up for the next cycle.

- safecall (func, ...)
  A modified copy of the xpcall wrapper duplicated in every Ace3 file in the
  whole damn library.

- new(...), del(t), copy(t), clear()
  Ditto for table recycling.
]]

local MAJOR, MINOR = "LibFarmbuyer", 12
assert(LibStub,MAJOR.." requires LibStub")
local lib = LibStub:NewLibrary(MAJOR, MINOR)
if not lib then return end

_G[MAJOR] = lib

----------------------------------------------------------------------
--[[
	Recycling functions yoinked from AceConfigDialog and tweaked
]]
local new, del, copy, clear
do
	local pool = setmetatable({},{__mode="k"})
	function clear()
		wipe(pool)
	end
	function new(...)  -- slightly modified variant, takes optional initializers
		local t = next(pool)
		if t then
			pool[t] = nil
			for i = 1, select('#',...) do
				t[i] = select(i,...)
			end
			return t
		else
			return {...}
		end
	end
	function copy(t)
		local c = new()
		for k, v in pairs(t) do
			c[k] = v
		end
		return c
	end
	function del(t)
		wipe(t)
		pool[t] = true
	end
end
lib.new, lib.del, lib.copy, lib.clear = new, del, copy, clear


----------------------------------------------------------------------
--[[
	safeprint
]]
local tconcat = table.concat
local function undocontrol(c)
	return ("\\%.3d"):format(c:byte())
end
function lib.safeprint(...)
	local args = { n=select('#',...), ... }
	return lib.tableprint(args)
end
function lib.safeiprint(...)
	local args = { n=select('#',...), ... }
	local last = args.n
	while last > 0 do
		table.insert (args, last, "<"..last..">")
		last = last - 1
	end
	args.n = 2 * args.n
	return lib.tableprint(args)
end
function lib.tableprint(t,f)
	for i = 1, (tonumber(t.n) or #t) do
		t[i] = tostring(t[i]):gsub('\124','\124\124')
		                     :gsub('(%c)', undocontrol)
	end
	local msg = tconcat(t,' ', i, tonumber(t.n) or #t)
	if f then
		return f(msg)
	else
		print(msg)
		return msg,t
	end
end

-- See below for global versions.


----------------------------------------------------------------------
local StaticPopupDialogs = _G.StaticPopupDialogs

local function EditBoxOnTextChanged_notempty (editbox) -- this is also called when first shown
	if editbox:GetText() ~= "" then
		editbox:GetParent().button1:Enable()
	else
		editbox:GetParent().button1:Disable()
	end
end
local function EditBoxOnEnterPressed_accept (editbox)
    local dialog = editbox:GetParent()
    StaticPopupDialogs[dialog.which].OnAccept (dialog, dialog.data, dialog.data2)
    dialog:Hide()
end
local function OnShow_witheditbox (dialog, data)
	local info = StaticPopupDialogs[dialog.which]
	--dialog[info.hasWideEditBox and "wideEditBox" or "editBox"]:SetFocus()
	dialog.editBox:SetFocus()
    if info.farm_OnShow then
        return info.farm_OnShow (dialog, data)
    end
end
local function OnAccept_witheditbox (dialog, data, data2)
	local info = StaticPopupDialogs[dialog.which]
	--dialog.usertext = dialog[info.hasWideEditBox and "wideEditBox" or "editBox"]:GetText():trim()
	dialog.usertext = dialog.editBox:GetText():trim()
    if info.farm_OnAccept then
        return info.farm_OnAccept (dialog, data, data2)
    end
end
local function OnHide_cleanup (dialog)
	dialog.data = nil
	dialog.data2 = nil
end

--[[
	StaticPopup
]]
function lib.StaticPopup (t)
    if t.hasEditBox then
        t.EditBoxOnTextChanged = EditBoxOnTextChanged_notempty
        t.EditBoxOnEnterPressed = EditBoxOnEnterPressed_accept
		if t.OnShow then
			t.farm_OnShow = t.OnShow
		end
        t.OnShow = OnShow_witheditbox
		if t.OnAccept then
			t.farm_OnAccept = t.OnAccept
		end
        t.OnAccept = OnAccept_witheditbox
		-- this calls OnCancel with "clicked", unless noCancelOnEscape is set
        t.EditBoxOnEscapePressed = StaticPopup_EscapePressed
    end

	if not t.OnHide then
		t.OnHide = OnHide_cleanup
	end

    t.timeout = 0
    t.whileDead = true
    t.hideOnEscape = true
	t.enterClicksFirstButton = true

    return t
end


----------------------------------------------------------------------
--[[
This is ugly, but at least it all gets GC'd almost immediately.
]]
function lib.nullfunc() end

if ({
	["Bandwagon"] = true, ["Kilvin"] = true, ["Waterfaucet"] = true,
	["Farmbuyer"] = true, ["Oxdeadbeef"] = true, ["Pointystick"] = true,
	["Angryhobbit"] = true, ["Malrubius"] = true, ["Hemogoblin"] = true,
	["Ossipago"] = true,
})[UnitName("player")] then
	lib.author_debug = true
	_G.safeprint = lib.safeprint
	_G.safeiprint = lib.safeiprint
	function lib.tabledump(t)
		_G.UIParentLoadAddOn("Blizzard_DebugTools")
		_G.LibF_DEBUG = t
		_G.SlashCmdList.DUMP("LibF_DEBUG")
	end
else
	lib.tabledump = lib.nullfunc
end
lib.dumptable = lib.tabledump


----------------------------------------------------------------------
--[[
	DoOnceNextUpdate
]]
do
	local frame = CreateFrame("Frame", "LibFarmbuyerDONUFrame")
	frame:Hide()
	frame:SetScript("OnUpdate", function()
		frame:Hide()
		local q = frame.nexttime
		local tmp
		frame.nexttime = nil
		while q do
			tmp = q
			q.f(frame)
			q = q.n
			del(tmp)
		end
	end)

	function lib.DoOnceNextUpdate (func)
		local nextt = new()
		nextt.f = func
		nextt.n = frame.nexttime
		frame.nexttime = nextt
		frame:Show()
	end
end


----------------------------------------------------------------------
--[[
	safecall
]]
do
	local xpcall = xpcall

	local function errorhandler(err)
		--return geterrorhandler()(err)
		--print("in error handler", err)
		return err
	end

	local template = ([[
		local xpcall, eh = ...
		local method, ARGS
		local function call() return method(ARGS) end

		local function dispatch (func, ...)
			 method = func
			 if not method then return end
			 ARGS = ...
			 return xpcall (call, eh)
		end

		return dispatch
	]]):gsub('\t','  ')

	local function CreateDispatcher(argCount)
		local ARGS = {}
		for i = 1, argCount do ARGS[i] = "arg"..i end
		local code = template:gsub("ARGS", tconcat(ARGS, ", "))
		return assert(loadstring(code, "LibF/safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
	end

	local Dispatchers = setmetatable({
		[0] = function(func)
			return xpcall (func, errorhandler)
		end
	}, {
		__index = function (Ds, argCount)
			local dispatcher = CreateDispatcher(argCount)
			Ds[argCount] = dispatcher
			return dispatcher
		end
	})

	function lib.safecall (func, ...)
		if type(func) == 'function' then
			return Dispatchers[select('#', ...)](func, ...)
		end
	end
end


----------------------------------------------------------------------

-- vim: noet