local M,d="\075\101\121\098\105\110\100\105\110\103",26 local l=LibStub and LibStub("\065\099\101\071\085\073-\051\046\048",true)if not l or(l:GetWidgetVersion(M)or 0)>=d then return end local U=pairs local j,v,x=IsShiftKeyDown,IsControlKeyDown,IsAltKeyDown local C,i=CreateFrame,UIParent local function A(M)M.obj:Fire("\079\110\069\110\116\101\114")end local function m(M)M.obj:Fire("\079\110\076\101\097\118\101")end local function f(M,d)if d=="\076\101\102\116\066\117\116\116\111\110"or d=="\082\105\103\104\116\066\117\116\116\111\110"then local d=M.obj if d.waitingForKey then M:EnableKeyboard(false)M:EnableMouseWheel(false)d.msgframe:Hide()M:UnlockHighlight()d.waitingForKey=nil else M:EnableKeyboard(true)M:EnableMouseWheel(true)d.msgframe:Show()M:LockHighlight()d.waitingForKey=true end end l:ClearFocus()end local K={BUTTON1=true;BUTTON2=true;UNKNOWN=true,LSHIFT=true;LCTRL=true;LALT=true;RSHIFT=true;RCTRL=true,RALT=true}local function P(M,d)local l=M.obj if l.waitingForKey then local U=d if U=="\069\083\067\065\080\069"then U=""else if K[U]then return end if j()then U="\083\072\073\070\084-"..U end if v()then U="\067\084\082\076-"..U end if x()then U="\065\076\084-"..U end end M:EnableKeyboard(false)M:EnableMouseWheel(false)l.msgframe:Hide()M:UnlockHighlight()l.waitingForKey=nil if not l.disabled then l:SetKey(U)l:Fire("\079\110\075\101\121\067\104\097\110\103\101\100",U)end end end local function Q(M,d)if d=="\076\101\102\116\066\117\116\116\111\110"or d=="\082\105\103\104\116\066\117\116\116\111\110"then return elseif d=="\077\105\100\100\108\101\066\117\116\116\111\110"then d="\066\085\084\084\079\078\051"elseif d=="\066\117\116\116\111\110\052"then d="\066\085\084\084\079\078\052"elseif d=="\066\117\116\116\111\110\053"then d="\066\085\084\084\079\078\053"end P(M,d)end local function N(M,d)local l if d>=0 then l="\077\079\085\083\069\087\072\069\069\076\085\080"else l="\077\079\085\083\069\087\072\069\069\076\068\079\087\078"end P(M,l)end local r={OnAcquire=function(M)M:SetWidth(200)M:SetLabel("")M:SetKey("")M.waitingForKey=nil M.msgframe:Hide()M:SetDisabled(false)M.button:EnableKeyboard(false)M.button:EnableMouseWheel(false)end;SetDisabled=function(M,d)M.disabled=d if d then M.button:Disable()M.label:SetTextColor(.5,.5,.5)else M.button:Enable()M.label:SetTextColor(1,1,1)end end,SetKey=function(M,d)if(d or"")==""then M.button:SetText(NOT_BOUND)M.button:SetNormalFontObject("\071\097\109\101\070\111\110\116\078\111\114\109\097\108")else M.button:SetText(d)M.button:SetNormalFontObject("\071\097\109\101\070\111\110\116\072\105\103\104\108\105\103\104\116")end end,GetKey=function(M)local d=M.button:GetText()if d==NOT_BOUND then d=nil end return d end;SetLabel=function(M,d)M.label:SetText(d or"")if(d or"")==""then M.alignoffset=nil M:SetHeight(24)else M.alignoffset=30 M:SetHeight(44)end end}local B={bgFile="\073\110\116\101\114\102\097\099\101\092\084\111\111\108\116\105\112\115\092\085\073-\084\111\111\108\116\105\112-\066\097\099\107\103\114\111\117\110\100";edgeFile="\073\110\116\101\114\102\097\099\101\092\084\111\111\108\116\105\112\115\092\085\073-\084\111\111\108\116\105\112-\066\111\114\100\101\114";tile=true,tileSize=16;edgeSize=16,insets={left=3;right=3;top=3,bottom=3}}local function z(M)M:SetWidth(M.msg:GetWidth()+10)M:SetScript("\079\110\085\112\100\097\116\101",nil)end local function J()local d="\065\099\101\071\085\073\051\048\075\101\121\098\105\110\100\105\110\103\066\117\116\116\111\110"..l:GetNextWidgetNum(M)local j=C("\070\114\097\109\101",nil,i)local v=C("\066\117\116\116\111\110",d,j,"\085\073\080\097\110\101\108\066\117\116\116\111\110\084\101\109\112\108\097\116\101")v:EnableMouse(true)v:EnableMouseWheel(false)v:RegisterForClicks("\065\110\121\068\111\119\110")v:SetScript("\079\110\069\110\116\101\114",A)v:SetScript("\079\110\076\101\097\118\101",m)v:SetScript("\079\110\067\108\105\099\107",f)v:SetScript("\079\110\075\101\121\068\111\119\110",P)v:SetScript("\079\110\077\111\117\115\101\068\111\119\110",Q)v:SetScript("\079\110\077\111\117\115\101\087\104\101\101\108",N)v:SetPoint("\066\079\084\084\079\077\076\069\070\084")v:SetPoint("\066\079\084\084\079\077\082\073\071\072\084")v:SetHeight(24)v:EnableKeyboard(false)local x=v:GetFontString()x:SetPoint("\076\069\070\084",7,0)x:SetPoint("\082\073\071\072\084",-7,0)local K=j:CreateFontString(nil,"\079\086\069\082\076\065\089","\071\097\109\101\070\111\110\116\072\105\103\104\108\105\103\104\116")K:SetPoint("\084\079\080\076\069\070\084")K:SetPoint("\084\079\080\082\073\071\072\084")K:SetJustifyH("\067\069\078\084\069\082")K:SetHeight(18)local J=C("\070\114\097\109\101",nil,i,"\066\097\099\107\100\114\111\112\084\101\109\112\108\097\116\101")J:SetHeight(30)J:SetBackdrop(B)J:SetBackdropColor(0,0,0)J:SetFrameStrata("\070\085\076\076\083\067\082\069\069\078\095\068\073\065\076\079\071")J:SetFrameLevel(1000)J:SetToplevel(true)local s=J:CreateFontString(nil,"\079\086\069\082\076\065\089","\071\097\109\101\070\111\110\116\078\111\114\109\097\108")s:SetText("\080\114\101\115\115 \097 \107\101\121 \116\111 \098\105\110\100\044 \069\083\067 \116\111 \099\108\101\097\114 \116\104\101 \098\105\110\100\105\110\103 \111\114 \099\108\105\099\107 \116\104\101 \098\117\116\116\111\110 \097\103\097\105\110 \116\111 \099\097\110\099\101\108\046")J.msg=s s:SetPoint("\084\079\080\076\069\070\084",5,-5)J:SetScript("\079\110\085\112\100\097\116\101",z)J:SetPoint("\066\079\084\084\079\077",v,"\084\079\080")J:Hide()local D={button=v,label=K;msgframe=J,frame=j;alignoffset=30,type=M}for M,d in U(r)do D[M]=d end v.obj=D return l:RegisterAsWidget(D)end l:RegisterWidgetType(M,J,d)
--[[-----------------------------------------------------------------------------
Keybinding Widget
Set Keybindings in the Config UI.
-------------------------------------------------------------------------------]]
local Type, Version = "Keybinding", 26
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end

-- Lua APIs
local pairs = pairs

-- WoW APIs
local IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown = IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown
local CreateFrame, UIParent = CreateFrame, UIParent

--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]

local function Control_OnEnter(frame)
	frame.obj:Fire("OnEnter")
end

local function Control_OnLeave(frame)
	frame.obj:Fire("OnLeave")
end

local function Keybinding_OnClick(frame, button)
	if button == "LeftButton" or button == "RightButton" then
		local self = frame.obj
		if self.waitingForKey then
			frame:EnableKeyboard(false)
			frame:EnableMouseWheel(false)
			self.msgframe:Hide()
			frame:UnlockHighlight()
			self.waitingForKey = nil
		else
			frame:EnableKeyboard(true)
			frame:EnableMouseWheel(true)
			self.msgframe:Show()
			frame:LockHighlight()
			self.waitingForKey = true
		end
	end
	AceGUI:ClearFocus()
end

local ignoreKeys = {
	["BUTTON1"] = true, ["BUTTON2"] = true,
	["UNKNOWN"] = true,
	["LSHIFT"] = true, ["LCTRL"] = true, ["LALT"] = true,
	["RSHIFT"] = true, ["RCTRL"] = true, ["RALT"] = true,
}
local function Keybinding_OnKeyDown(frame, key)
	local self = frame.obj
	if self.waitingForKey then
		local keyPressed = key
		if keyPressed == "ESCAPE" then
			keyPressed = ""
		else
			if ignoreKeys[keyPressed] then return end
			if IsShiftKeyDown() then
				keyPressed = "SHIFT-"..keyPressed
			end
			if IsControlKeyDown() then
				keyPressed = "CTRL-"..keyPressed
			end
			if IsAltKeyDown() then
				keyPressed = "ALT-"..keyPressed
			end
		end

		frame:EnableKeyboard(false)
		frame:EnableMouseWheel(false)
		self.msgframe:Hide()
		frame:UnlockHighlight()
		self.waitingForKey = nil

		if not self.disabled then
			self:SetKey(keyPressed)
			self:Fire("OnKeyChanged", keyPressed)
		end
	end
end

local function Keybinding_OnMouseDown(frame, button)
	if button == "LeftButton" or button == "RightButton" then
		return
	elseif button == "MiddleButton" then
		button = "BUTTON3"
	elseif button == "Button4" then
		button = "BUTTON4"
	elseif button == "Button5" then
		button = "BUTTON5"
	end
	Keybinding_OnKeyDown(frame, button)
end

local function Keybinding_OnMouseWheel(frame, direction)
	local button
	if direction >= 0 then
		button = "MOUSEWHEELUP"
	else
		button = "MOUSEWHEELDOWN"
	end
	Keybinding_OnKeyDown(frame, button)
end

--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
	["OnAcquire"] = function(self)
		self:SetWidth(200)
		self:SetLabel("")
		self:SetKey("")
		self.waitingForKey = nil
		self.msgframe:Hide()
		self:SetDisabled(false)
		self.button:EnableKeyboard(false)
		self.button:EnableMouseWheel(false)
	end,

	-- ["OnRelease"] = nil,

	["SetDisabled"] = function(self, disabled)
		self.disabled = disabled
		if disabled then
			self.button:Disable()
			self.label:SetTextColor(0.5,0.5,0.5)
		else
			self.button:Enable()
			self.label:SetTextColor(1,1,1)
		end
	end,

	["SetKey"] = function(self, key)
		if (key or "") == "" then
			self.button:SetText(NOT_BOUND)
			self.button:SetNormalFontObject("GameFontNormal")
		else
			self.button:SetText(key)
			self.button:SetNormalFontObject("GameFontHighlight")
		end
	end,

	["GetKey"] = function(self)
		local key = self.button:GetText()
		if key == NOT_BOUND then
			key = nil
		end
		return key
	end,

	["SetLabel"] = function(self, label)
		self.label:SetText(label or "")
		if (label or "") == "" then
			self.alignoffset = nil
			self:SetHeight(24)
		else
			self.alignoffset = 30
			self:SetHeight(44)
		end
	end,
}

--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]

local ControlBackdrop  = {
	bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
	edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
	tile = true, tileSize = 16, edgeSize = 16,
	insets = { left = 3, right = 3, top = 3, bottom = 3 }
}

local function keybindingMsgFixWidth(frame)
	frame:SetWidth(frame.msg:GetWidth() + 10)
	frame:SetScript("OnUpdate", nil)
end

local function Constructor()
	local name = "AceGUI30KeybindingButton" .. AceGUI:GetNextWidgetNum(Type)

	local frame = CreateFrame("Frame", nil, UIParent)
	local button = CreateFrame("Button", name, frame, "UIPanelButtonTemplate")

	button:EnableMouse(true)
	button:EnableMouseWheel(false)
	button:RegisterForClicks("AnyDown")
	button:SetScript("OnEnter", Control_OnEnter)
	button:SetScript("OnLeave", Control_OnLeave)
	button:SetScript("OnClick", Keybinding_OnClick)
	button:SetScript("OnKeyDown", Keybinding_OnKeyDown)
	button:SetScript("OnMouseDown", Keybinding_OnMouseDown)
	button:SetScript("OnMouseWheel", Keybinding_OnMouseWheel)
	button:SetPoint("BOTTOMLEFT")
	button:SetPoint("BOTTOMRIGHT")
	button:SetHeight(24)
	button:EnableKeyboard(false)

	local text = button:GetFontString()
	text:SetPoint("LEFT", 7, 0)
	text:SetPoint("RIGHT", -7, 0)

	local label = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
	label:SetPoint("TOPLEFT")
	label:SetPoint("TOPRIGHT")
	label:SetJustifyH("CENTER")
	label:SetHeight(18)

	local msgframe = CreateFrame("Frame", nil, UIParent, "BackdropTemplate")
	msgframe:SetHeight(30)
	msgframe:SetBackdrop(ControlBackdrop)
	msgframe:SetBackdropColor(0,0,0)
	msgframe:SetFrameStrata("FULLSCREEN_DIALOG")
	msgframe:SetFrameLevel(1000)
	msgframe:SetToplevel(true)

	local msg = msgframe:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	msg:SetText("Press a key to bind, ESC to clear the binding or click the button again to cancel.")
	msgframe.msg = msg
	msg:SetPoint("TOPLEFT", 5, -5)
	msgframe:SetScript("OnUpdate", keybindingMsgFixWidth)
	msgframe:SetPoint("BOTTOM", button, "TOP")
	msgframe:Hide()

	local widget = {
		button      = button,
		label       = label,
		msgframe    = msgframe,
		frame       = frame,
		alignoffset = 30,
		type        = Type
	}
	for method, func in pairs(methods) do
		widget[method] = func
	end
	button.obj = widget

	return AceGUI:RegisterAsWidget(widget)
end

AceGUI:RegisterWidgetType(Type, Constructor, Version)
