local h=LibStub("\065\099\101\071\085\073-\051\046\048")local m,t,a=math.min,math.max,math.floor local N,z,s,S,g=select,pairs,ipairs,type,tostring local i=table.sort local j=PlaySound local D,U=UIParent,CreateFrame local E=_G local function Q(h,...)local m=1 local t=N(m,...)while t do t:SetFrameLevel(h:GetFrameLevel()+1)Q(t,t:GetChildren())m=m+1 t=N(m,...)end end local function L(h,m,...)local t=1 local a=N(t,...)m:SetFrameStrata(h)while a do L(h,a,a:GetChildren())t=t+1 a=N(t,...)end end do local N="\068\114\111\112\100\111\119\110-\080\117\108\108\111\117\116"local S=5 local g={bgFile="\073\110\116\101\114\102\097\099\101\092\067\104\097\116\070\114\097\109\101\092\067\104\097\116\070\114\097\109\101\066\097\099\107\103\114\111\117\110\100";edgeFile="\073\110\116\101\114\102\097\099\101\092\068\105\097\108\111\103\070\114\097\109\101\092\085\073-\068\105\097\108\111\103\066\111\120-\066\111\114\100\101\114",edgeSize=32;tileSize=32;tile=true;insets={left=11,right=12;top=12,bottom=11}}local i={bgFile="\073\110\116\101\114\102\097\099\101\092\066\117\116\116\111\110\115\092\085\073-\083\108\105\100\101\114\066\097\114-\066\097\099\107\103\114\111\117\110\100";edgeFile="\073\110\116\101\114\102\097\099\101\092\066\117\116\116\111\110\115\092\085\073-\083\108\105\100\101\114\066\097\114-\066\111\114\100\101\114";tile=true;tileSize=8,edgeSize=8,insets={left=3,right=3,top=3;bottom=3}}local j=200 local E=600 local function Q(h)local m=h.pullout for m,t in s(m.items)do if t.CloseMenu and t~=h then t:CloseMenu()end end end local function H(h,m)h.obj:MoveScroll(m)end local function y(h,m)h.obj:SetScroll(m)end local function J(h)h.obj:FixScroll()end local function f(h,m)local t=h.scrollStatus local N,z=h.scrollFrame,h.itemFrame local s,S=N:GetHeight(),z:GetHeight()local g if s>S then g=0 else g=a(((S-s)/1000)*m)end z:ClearAllPoints()z:SetPoint("\084\079\080\076\069\070\084",N,"\084\079\080\076\069\070\084",0,g)z:SetPoint("\084\079\080\082\073\071\072\084",N,"\084\079\080\082\073\071\072\084",h.slider:IsShown()and-12 or 0,g)t.offset=g t.scrollvalue=m end local function W(h,a)local N=h.scrollStatus local z,s=h.scrollFrame,h.itemFrame local S,g=z:GetHeight(),s:GetHeight()if S>g then h.slider:Hide()else h.slider:Show()local z=S-g local s=1 if a<0 then s=-1 end h.slider:SetValue(m(t(N.scrollvalue+s*(1000/(z/45)),0),1000))end end local function P(h)local m=h.scrollStatus local t,a=h.scrollFrame,h.itemFrame local N,z=t:GetHeight(),a:GetHeight()local s=m.offset or 0 if z<N then h.slider:Hide()a:SetPoint("\084\079\080\082\073\071\072\084",t,"\084\079\080\082\073\071\072\084",0,s)h.slider:SetValue(0)else h.slider:Show()local S=(s/(z-N))*1000 if S>1000 then S=1000 end h.slider:SetValue(S)h:SetScroll(S)if S<1000 then a:ClearAllPoints()a:SetPoint("\084\079\080\076\069\070\084",t,"\084\079\080\076\069\070\084",0,s)a:SetPoint("\084\079\080\082\073\071\072\084",t,"\084\079\080\082\073\071\072\084",-12,s)m.offset=s end end end local function R(h)h.frame:SetParent(D)end local function v(h)h:Clear()h.frame:ClearAllPoints()h.frame:Hide()end local function q(h,t)h.items[#h.items+1]=t local a=#h.items*16 h.itemFrame:SetHeight(a)h.frame:SetHeight(m(a+34,h.maxHeight))t.frame:SetPoint("\076\069\070\084",h.itemFrame,"\076\069\070\084")t.frame:SetPoint("\082\073\071\072\084",h.itemFrame,"\082\073\071\072\084")t:SetPullout(h)t:SetOnEnter(Q)end local function T(h,m,t,a,N,s)local S=h.items local g=h.frame local i=h.itemFrame g:SetPoint(m,t,a,N,s)local j=8 for h,m in z(S)do m:SetPoint("\084\079\080",i,"\084\079\080",0,-2+(h-1)*-16)m:Show()j=j+16 end i:SetHeight(j)L("\084\079\079\076\084\073\080",g,g:GetChildren())g:Show()h:Fire("\079\110\079\112\101\110")end local function x(h)h.frame:Hide()h:Fire("\079\110\067\108\111\115\101")end local function b(m)local t=m.items for m,a in z(t)do h:Release(a)t[m]=nil end end local function u(h)return s(h.items)end local function d(h,m)h.hideOnLeave=m end local function G(h,m)h.maxHeight=m or E if h.frame:GetHeight()>m then h.frame:SetHeight(m)elseif h.itemFrame:GetHeight()+34<m then h.frame:SetHeight(h.itemFrame:GetHeight()+34)end end local function A(h)return 6+(h.slider:IsShown()and 12 or 0)end local function k(h)return 6 end local function o()local m=h:GetNextWidgetNum(N)local t=U("\070\114\097\109\101","\065\099\101\071\085\073\051\048\080\117\108\108\111\117\116"..m,D,"\066\097\099\107\100\114\111\112\084\101\109\112\108\097\116\101")local a={}a.count=m a.type=N a.frame=t t.obj=a a.OnAcquire=R a.OnRelease=v a.AddItem=q a.Open=T a.Close=x a.Clear=b a.IterateItems=u a.SetHideOnLeave=d a.SetScroll=f a.MoveScroll=W a.FixScroll=P a.SetMaxHeight=G a.GetRightBorderWidth=A a.GetLeftBorderWidth=k a.items={}a.scrollStatus={scrollvalue=0}a.maxHeight=E t:SetBackdrop(g)t:SetBackdropColor(0,0,0)t:SetFrameStrata("\070\085\076\076\083\067\082\069\069\078\095\068\073\065\076\079\071")t:SetClampedToScreen(true)t:SetWidth(j)t:SetHeight(a.maxHeight)local z=U("\083\099\114\111\108\108\070\114\097\109\101",nil,t)local s=U("\070\114\097\109\101",nil,z)a.scrollFrame=z a.itemFrame=s z.obj=a s.obj=a local S=U("\083\108\105\100\101\114","\065\099\101\071\085\073\051\048\080\117\108\108\111\117\116\083\099\114\111\108\108\098\097\114"..m,z,"\066\097\099\107\100\114\111\112\084\101\109\112\108\097\116\101")S:SetOrientation("\086\069\082\084\073\067\065\076")S:SetHitRectInsets(0,0,-10,0)S:SetBackdrop(i)S:SetWidth(8)S:SetThumbTexture("\073\110\116\101\114\102\097\099\101\092\066\117\116\116\111\110\115\092\085\073-\083\108\105\100\101\114\066\097\114-\066\117\116\116\111\110-\086\101\114\116\105\099\097\108")S:SetFrameStrata("\070\085\076\076\083\067\082\069\069\078\095\068\073\065\076\079\071")a.slider=S S.obj=a z:SetScrollChild(s)z:SetPoint("\084\079\080\076\069\070\084",t,"\084\079\080\076\069\070\084",6,-12)z:SetPoint("\066\079\084\084\079\077\082\073\071\072\084",t,"\066\079\084\084\079\077\082\073\071\072\084",-6,12)z:EnableMouseWheel(true)z:SetScript("\079\110\077\111\117\115\101\087\104\101\101\108",H)z:SetScript("\079\110\083\105\122\101\067\104\097\110\103\101\100",J)z:SetToplevel(true)z:SetFrameStrata("\070\085\076\076\083\067\082\069\069\078\095\068\073\065\076\079\071")s:SetPoint("\084\079\080\076\069\070\084",z,"\084\079\080\076\069\070\084",0,0)s:SetPoint("\084\079\080\082\073\071\072\084",z,"\084\079\080\082\073\071\072\084",-12,0)s:SetHeight(400)s:SetToplevel(true)s:SetFrameStrata("\070\085\076\076\083\067\082\069\069\078\095\068\073\065\076\079\071")S:SetPoint("\084\079\080\076\069\070\084",z,"\084\079\080\082\073\071\072\084",-16,0)S:SetPoint("\066\079\084\084\079\077\076\069\070\084",z,"\066\079\084\084\079\077\082\073\071\072\084",-16,0)S:SetScript("\079\110\086\097\108\117\101\067\104\097\110\103\101\100",y)S:SetMinMaxValues(0,1000)S:SetValueStep(1)S:SetValue(0)z:Show()s:Show()S:Hide()a:FixScroll()h:RegisterAsWidget(a)return a end h:RegisterWidgetType(N,o,S)end do local m="\068\114\111\112\100\111\119\110"local t=36 local function a(h)h.obj.button:LockHighlight()h.obj:Fire("\079\110\069\110\116\101\114")end local function N(h)h.obj.button:UnlockHighlight()h.obj:Fire("\079\110\076\101\097\118\101")end local function j(h)local m=h.obj if m.open then m.pullout:Close()end end local function L(m)local t=m.obj if t.open then t.open=nil t.pullout:Close()h:ClearFocus()else t.open=true t.pullout:SetWidth(t.pulloutWidth or t.frame:GetWidth())t.pullout:Open("\084\079\080\076\069\070\084",t.frame,"\066\079\084\084\079\077\076\069\070\084",0,t.label:IsShown()and-2 or 0)h:SetFocus(t)end end local function H(h)local m=h.userdata.obj local t=m.value if not m.multiselect then for h,m in h:IterateItems()do m:SetValue(m.userdata.value==t)end end m.open=true m:Fire("\079\110\079\112\101\110\101\100")end local function y(h)local m=h.userdata.obj m.open=nil m:Fire("\079\110\067\108\111\115\101\100")end local function J(h)local m for h,t in h.pullout:IterateItems()do if t.type=="\068\114\111\112\100\111\119\110-\073\116\101\109-\084\111\103\103\108\101"then if t:GetValue()then if m then m=m..("\044 "..t:GetText())else m=t:GetText()end end end end h:SetText(m)end local function f(h,m,t)local a=h.userdata.obj if a.multiselect then a:Fire("\079\110\086\097\108\117\101\067\104\097\110\103\101\100",h.userdata.value,t)J(a)else if t then a:SetValue(h.userdata.value)a:Fire("\079\110\086\097\108\117\101\067\104\097\110\103\101\100",h.userdata.value)else h:SetValue(true)end if a.open then a.pullout:Close()end end end local function W(m)local t=h:Create("\068\114\111\112\100\111\119\110-\080\117\108\108\111\117\116")m.pullout=t t.userdata.obj=m t:SetCallback("\079\110\067\108\111\115\101",y)t:SetCallback("\079\110\079\112\101\110",H)m.pullout.frame:SetFrameLevel(m.frame:GetFrameLevel()+1)Q(m.pullout.frame,m.pullout.frame:GetChildren())m:SetHeight(44)m:SetWidth(200)m:SetLabel()m:SetPulloutWidth(nil)m.list={}end local function P(m)if m.open then m.pullout:Close()end h:Release(m.pullout)m.pullout=nil m:SetText("")m:SetDisabled(false)m:SetMultiselect(false)m.value=nil m.list=nil m.open=nil m.hasClose=nil m.frame:ClearAllPoints()m.frame:Hide()end local function R(h,m)h.disabled=m if m then h.text:SetTextColor(.5,.5,.5)h.button:Disable()h.button_cover:Disable()h.label:SetTextColor(.5,.5,.5)else h.button:Enable()h.button_cover:Enable()h.label:SetTextColor(1,.82,0)h.text:SetTextColor(1,1,1)end end local function v(h)if h.open then h.pullout:Close()end end local function q(h,m)h.text:SetText(m or"")end local function T(h,m)if m and m~=""then h.label:SetText(m)h.label:Show()h.dropdown:SetPoint("\084\079\080\076\069\070\084",h.frame,"\084\079\080\076\069\070\084",-15,-14)h:SetHeight(40)h.alignoffset=26 else h.label:SetText("")h.label:Hide()h.dropdown:SetPoint("\084\079\080\076\069\070\084",h.frame,"\084\079\080\076\069\070\084",-15,0)h:SetHeight(26)h.alignoffset=12 end end local function x(h,m)h:SetText(h.list[m]or"")h.value=m end local function b(h)return h.value end local function u(h,m,t)if not h.multiselect then return end for h,a in h.pullout:IterateItems()do if a.userdata.value==m then if a.SetValue then a:SetValue(t)end end end J(h)end local function d(h,m,t)for h,a in h.pullout:IterateItems()do if a.userdata.value==m then a:SetDisabled(t)end end end local function G(m,t,a,N)if not N then N="\068\114\111\112\100\111\119\110-\073\116\101\109-\084\111\103\103\108\101"end local z=h:GetWidgetVersion(N)if not z then error(("\084\104\101 \103\105\118\101\110 \105\116\101\109 \116\121\112\101\044 \037\113\044 \100\111\101\115 \110\111\116 \101\120\105\115\116 \119\105\116\104\105\110 \065\099\101\071\085\073-\051\046\048"):format(g(N)),2)end local s=h:Create(N)s:SetText(a)s.userdata.obj=m s.userdata.value=t s:SetCallback("\079\110\086\097\108\117\101\067\104\097\110\103\101\100",f)m.pullout:AddItem(s)end local function A(m)if not m.hasClose then local t=h:Create("\068\114\111\112\100\111\119\110-\073\116\101\109-\069\120\101\099\117\116\101")t:SetText(CLOSE)m.pullout:AddItem(t)m.hasClose=true end end local k={}local function o(h,m)local t,a=tonumber(h),tonumber(m)if t and a then return t<a else return g(h)<g(m)end end local function B(h,m,t,a)h.list=m or{}h.pullout:Clear()h.hasClose=nil if not m then return end if S(t)~="\116\097\098\108\101"then for h in z(m)do k[#k+1]=h end i(k,o)for t,N in s(k)do G(h,N,m[N],a)k[t]=nil end else for t,N in s(t)do G(h,N,m[N],a)end end if h.multiselect then J(h)A(h)end end local function F(h,m,t,a)h.list[m]=t G(h,m,t,a)end local function e(h,m)h.multiselect=m if m then J(h)A(h)end end local function r(h)return h.multiselect end local function K(h,m)h.pulloutWidth=m end local function p()local t=h:GetNextWidgetNum(m)local z=U("\070\114\097\109\101",nil,D)local s=U("\070\114\097\109\101","\065\099\101\071\085\073\051\048\068\114\111\112\068\111\119\110"..t,z,"\085\073\068\114\111\112\068\111\119\110\077\101\110\117\084\101\109\112\108\097\116\101")local S={}S.type=m S.frame=z S.dropdown=s S.count=t z.obj=S s.obj=S S.OnRelease=P S.OnAcquire=W S.ClearFocus=v S.SetText=q S.SetValue=x S.GetValue=b S.SetList=B S.SetLabel=T S.SetDisabled=R S.AddItem=F S.SetMultiselect=e S.GetMultiselect=r S.SetItemValue=u S.SetItemDisabled=d S.SetPulloutWidth=K S.alignoffset=26 z:SetScript("\079\110\072\105\100\101",j)s:ClearAllPoints()s:SetPoint("\084\079\080\076\069\070\084",z,"\084\079\080\076\069\070\084",-15,0)s:SetPoint("\066\079\084\084\079\077\082\073\071\072\084",z,"\066\079\084\084\079\077\082\073\071\072\084",17,0)s:SetScript("\079\110\072\105\100\101",nil)local g=E[s:GetName().."\076\101\102\116"]local i=E[s:GetName().."\077\105\100\100\108\101"]local Q=E[s:GetName().."\082\105\103\104\116"]i:ClearAllPoints()Q:ClearAllPoints()i:SetPoint("\076\069\070\084",g,"\082\073\071\072\084",0,0)i:SetPoint("\082\073\071\072\084",Q,"\076\069\070\084",0,0)Q:SetPoint("\084\079\080\082\073\071\072\084",s,"\084\079\080\082\073\071\072\084",0,17)local H=E[s:GetName().."\066\117\116\116\111\110"]S.button=H H.obj=S H:SetScript("\079\110\069\110\116\101\114",a)H:SetScript("\079\110\076\101\097\118\101",N)H:SetScript("\079\110\067\108\105\099\107",L)local y=U("\066\085\084\084\079\078",nil,S.frame)S.button_cover=y y.obj=S y:SetPoint("\084\079\080\076\069\070\084",S.frame,"\066\079\084\084\079\077\076\069\070\084",0,25)y:SetPoint("\066\079\084\084\079\077\082\073\071\072\084",S.frame,"\066\079\084\084\079\077\082\073\071\072\084")y:SetScript("\079\110\069\110\116\101\114",a)y:SetScript("\079\110\076\101\097\118\101",N)y:SetScript("\079\110\067\108\105\099\107",L)local J=E[s:GetName().."\084\101\120\116"]S.text=J J.obj=S J:ClearAllPoints()J:SetPoint("\082\073\071\072\084",Q,"\082\073\071\072\084",-43,2)J:SetPoint("\076\069\070\084",g,"\076\069\070\084",25,2)local f=z:CreateFontString(nil,"\079\086\069\082\076\065\089","\071\097\109\101\070\111\110\116\078\111\114\109\097\108\083\109\097\108\108")f:SetPoint("\084\079\080\076\069\070\084",z,"\084\079\080\076\069\070\084",0,0)f:SetPoint("\084\079\080\082\073\071\072\084",z,"\084\079\080\082\073\071\072\084",0,0)f:SetJustifyH("\076\069\070\084")f:SetHeight(18)f:Hide()S.label=f h:RegisterAsWidget(S)return S end h:RegisterWidgetType(m,p,t)end
--[[ $Id: AceGUIWidget-DropDown.lua 1284 2022-09-25 09:15:30Z nevcairiel $ ]]--
local AceGUI = LibStub("AceGUI-3.0")

-- Lua APIs
local min, max, floor = math.min, math.max, math.floor
local select, pairs, ipairs, type, tostring = select, pairs, ipairs, type, tostring
local tsort = table.sort

-- WoW APIs
local PlaySound = PlaySound
local UIParent, CreateFrame = UIParent, CreateFrame
local _G = _G

local function fixlevels(parent,...)
	local i = 1
	local child = select(i, ...)
	while child do
		child:SetFrameLevel(parent:GetFrameLevel()+1)
		fixlevels(child, child:GetChildren())
		i = i + 1
		child = select(i, ...)
	end
end

local function fixstrata(strata, parent, ...)
	local i = 1
	local child = select(i, ...)
	parent:SetFrameStrata(strata)
	while child do
		fixstrata(strata, child, child:GetChildren())
		i = i + 1
		child = select(i, ...)
	end
end

do
	local widgetType = "Dropdown-Pullout"
	local widgetVersion = 5

	--[[ Static data ]]--

	local backdrop = {
		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
		edgeSize = 32,
		tileSize = 32,
		tile = true,
		insets = { left = 11, right = 12, top = 12, bottom = 11 },
	}
	local sliderBackdrop  = {
		bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
		edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
		tile = true, tileSize = 8, edgeSize = 8,
		insets = { left = 3, right = 3, top = 3, bottom = 3 }
	}

	local defaultWidth = 200
	local defaultMaxHeight = 600

	--[[ UI Event Handlers ]]--

	-- HACK: This should be no part of the pullout, but there
	--       is no other 'clean' way to response to any item-OnEnter
	--       Used to close Submenus when an other item is entered
	local function OnEnter(item)
		local self = item.pullout
		for k, v in ipairs(self.items) do
			if v.CloseMenu and v ~= item then
				v:CloseMenu()
			end
		end
	end

	-- See the note in Constructor() for each scroll related function
	local function OnMouseWheel(this, value)
		this.obj:MoveScroll(value)
	end

	local function OnScrollValueChanged(this, value)
		this.obj:SetScroll(value)
	end

	local function OnSizeChanged(this)
		this.obj:FixScroll()
	end

	--[[ Exported methods ]]--

	-- exported
	local function SetScroll(self, value)
		local status = self.scrollStatus
		local frame, child = self.scrollFrame, self.itemFrame
		local height, viewheight = frame:GetHeight(), child:GetHeight()

		local offset
		if height > viewheight then
			offset = 0
		else
			offset = floor((viewheight - height) / 1000 * value)
		end
		child:ClearAllPoints()
		child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
		child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", self.slider:IsShown() and -12 or 0, offset)
		status.offset = offset
		status.scrollvalue = value
	end

	-- exported
	local function MoveScroll(self, value)
		local status = self.scrollStatus
		local frame, child = self.scrollFrame, self.itemFrame
		local height, viewheight = frame:GetHeight(), child:GetHeight()

		if height > viewheight then
			self.slider:Hide()
		else
			self.slider:Show()
			local diff = height - viewheight
			local delta = 1
			if value < 0 then
				delta = -1
			end
			self.slider:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
		end
	end

	-- exported
	local function FixScroll(self)
		local status = self.scrollStatus
		local frame, child = self.scrollFrame, self.itemFrame
		local height, viewheight = frame:GetHeight(), child:GetHeight()
		local offset = status.offset or 0

		if viewheight < height then
			self.slider:Hide()
			child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, offset)
			self.slider:SetValue(0)
		else
			self.slider:Show()
			local value = (offset / (viewheight - height) * 1000)
			if value > 1000 then value = 1000 end
			self.slider:SetValue(value)
			self:SetScroll(value)
			if value < 1000 then
				child:ClearAllPoints()
				child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
				child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -12, offset)
				status.offset = offset
			end
		end
	end

	-- exported, AceGUI callback
	local function OnAcquire(self)
		self.frame:SetParent(UIParent)
		--self.itemFrame:SetToplevel(true)
	end

	-- exported, AceGUI callback
	local function OnRelease(self)
		self:Clear()
		self.frame:ClearAllPoints()
		self.frame:Hide()
	end

	-- exported
	local function AddItem(self, item)
		self.items[#self.items + 1] = item

		local h = #self.items * 16
		self.itemFrame:SetHeight(h)
		self.frame:SetHeight(min(h + 34, self.maxHeight)) -- +34: 20 for scrollFrame placement (10 offset) and +14 for item placement

		item.frame:SetPoint("LEFT", self.itemFrame, "LEFT")
		item.frame:SetPoint("RIGHT", self.itemFrame, "RIGHT")

		item:SetPullout(self)
		item:SetOnEnter(OnEnter)
	end

	-- exported
	local function Open(self, point, relFrame, relPoint, x, y)
		local items = self.items
		local frame = self.frame
		local itemFrame = self.itemFrame

		frame:SetPoint(point, relFrame, relPoint, x, y)


		local height = 8
		for i, item in pairs(items) do
			item:SetPoint("TOP", itemFrame, "TOP", 0, -2 + (i - 1) * -16)
			item:Show()

			height = height + 16
		end
		itemFrame:SetHeight(height)
		fixstrata("TOOLTIP", frame, frame:GetChildren())
		frame:Show()
		self:Fire("OnOpen")
	end

	-- exported
	local function Close(self)
		self.frame:Hide()
		self:Fire("OnClose")
	end

	-- exported
	local function Clear(self)
		local items = self.items
		for i, item in pairs(items) do
			AceGUI:Release(item)
			items[i] = nil
		end
	end

	-- exported
	local function IterateItems(self)
		return ipairs(self.items)
	end

	-- exported
	local function SetHideOnLeave(self, val)
		self.hideOnLeave = val
	end

	-- exported
	local function SetMaxHeight(self, height)
		self.maxHeight = height or defaultMaxHeight
		if self.frame:GetHeight() > height then
			self.frame:SetHeight(height)
		elseif (self.itemFrame:GetHeight() + 34) < height then
			self.frame:SetHeight(self.itemFrame:GetHeight() + 34) -- see :AddItem
		end
	end

	-- exported
	local function GetRightBorderWidth(self)
		return 6 + (self.slider:IsShown() and 12 or 0)
	end

	-- exported
	local function GetLeftBorderWidth(self)
		return 6
	end

	--[[ Constructor ]]--

	local function Constructor()
		local count = AceGUI:GetNextWidgetNum(widgetType)
		local frame = CreateFrame("Frame", "AceGUI30Pullout"..count, UIParent, "BackdropTemplate")
		local self = {}
		self.count = count
		self.type = widgetType
		self.frame = frame
		frame.obj = self

		self.OnAcquire = OnAcquire
		self.OnRelease = OnRelease

		self.AddItem = AddItem
		self.Open    = Open
		self.Close   = Close
		self.Clear   = Clear
		self.IterateItems = IterateItems
		self.SetHideOnLeave = SetHideOnLeave

		self.SetScroll  = SetScroll
		self.MoveScroll = MoveScroll
		self.FixScroll  = FixScroll

		self.SetMaxHeight = SetMaxHeight
		self.GetRightBorderWidth = GetRightBorderWidth
		self.GetLeftBorderWidth = GetLeftBorderWidth

		self.items = {}

		self.scrollStatus = {
			scrollvalue = 0,
		}

		self.maxHeight = defaultMaxHeight

		frame:SetBackdrop(backdrop)
		frame:SetBackdropColor(0, 0, 0)
		frame:SetFrameStrata("FULLSCREEN_DIALOG")
		frame:SetClampedToScreen(true)
		frame:SetWidth(defaultWidth)
		frame:SetHeight(self.maxHeight)
		--frame:SetToplevel(true)

		-- NOTE: The whole scroll frame code is copied from the AceGUI-3.0 widget ScrollFrame
		local scrollFrame = CreateFrame("ScrollFrame", nil, frame)
		local itemFrame = CreateFrame("Frame", nil, scrollFrame)

		self.scrollFrame = scrollFrame
		self.itemFrame = itemFrame

		scrollFrame.obj = self
		itemFrame.obj = self

		local slider = CreateFrame("Slider", "AceGUI30PulloutScrollbar"..count, scrollFrame, "BackdropTemplate")
		slider:SetOrientation("VERTICAL")
		slider:SetHitRectInsets(0, 0, -10, 0)
		slider:SetBackdrop(sliderBackdrop)
		slider:SetWidth(8)
		slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
		slider:SetFrameStrata("FULLSCREEN_DIALOG")
		self.slider = slider
		slider.obj = self

		scrollFrame:SetScrollChild(itemFrame)
		scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 6, -12)
		scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -6, 12)
		scrollFrame:EnableMouseWheel(true)
		scrollFrame:SetScript("OnMouseWheel", OnMouseWheel)
		scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
		scrollFrame:SetToplevel(true)
		scrollFrame:SetFrameStrata("FULLSCREEN_DIALOG")

		itemFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0)
		itemFrame:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", -12, 0)
		itemFrame:SetHeight(400)
		itemFrame:SetToplevel(true)
		itemFrame:SetFrameStrata("FULLSCREEN_DIALOG")

		slider:SetPoint("TOPLEFT", scrollFrame, "TOPRIGHT", -16, 0)
		slider:SetPoint("BOTTOMLEFT", scrollFrame, "BOTTOMRIGHT", -16, 0)
		slider:SetScript("OnValueChanged", OnScrollValueChanged)
		slider:SetMinMaxValues(0, 1000)
		slider:SetValueStep(1)
		slider:SetValue(0)

		scrollFrame:Show()
		itemFrame:Show()
		slider:Hide()

		self:FixScroll()

		AceGUI:RegisterAsWidget(self)
		return self
	end

	AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
end

do
	local widgetType = "Dropdown"
	local widgetVersion = 36

	--[[ Static data ]]--

	--[[ UI event handler ]]--

	local function Control_OnEnter(this)
		this.obj.button:LockHighlight()
		this.obj:Fire("OnEnter")
	end

	local function Control_OnLeave(this)
		this.obj.button:UnlockHighlight()
		this.obj:Fire("OnLeave")
	end

	local function Dropdown_OnHide(this)
		local self = this.obj
		if self.open then
			self.pullout:Close()
		end
	end

	local function Dropdown_TogglePullout(this)
		local self = this.obj
		if self.open then
			self.open = nil
			self.pullout:Close()
			AceGUI:ClearFocus()
		else
			self.open = true
			self.pullout:SetWidth(self.pulloutWidth or self.frame:GetWidth())
			self.pullout:Open("TOPLEFT", self.frame, "BOTTOMLEFT", 0, self.label:IsShown() and -2 or 0)
			AceGUI:SetFocus(self)
		end
	end

	local function OnPulloutOpen(this)
		local self = this.userdata.obj
		local value = self.value

		if not self.multiselect then
			for i, item in this:IterateItems() do
				item:SetValue(item.userdata.value == value)
			end
		end

		self.open = true
		self:Fire("OnOpened")
	end

	local function OnPulloutClose(this)
		local self = this.userdata.obj
		self.open = nil
		self:Fire("OnClosed")
	end

	local function ShowMultiText(self)
		local text
		for i, widget in self.pullout:IterateItems() do
			if widget.type == "Dropdown-Item-Toggle" then
				if widget:GetValue() then
					if text then
						text = text..", "..widget:GetText()
					else
						text = widget:GetText()
					end
				end
			end
		end
		self:SetText(text)
	end

	local function OnItemValueChanged(this, event, checked)
		local self = this.userdata.obj

		if self.multiselect then
			self:Fire("OnValueChanged", this.userdata.value, checked)
			ShowMultiText(self)
		else
			if checked then
				self:SetValue(this.userdata.value)
				self:Fire("OnValueChanged", this.userdata.value)
			else
				this:SetValue(true)
			end
			if self.open then
				self.pullout:Close()
			end
		end
	end

	--[[ Exported methods ]]--

	-- exported, AceGUI callback
	local function OnAcquire(self)
		local pullout = AceGUI:Create("Dropdown-Pullout")
		self.pullout = pullout
		pullout.userdata.obj = self
		pullout:SetCallback("OnClose", OnPulloutClose)
		pullout:SetCallback("OnOpen", OnPulloutOpen)
		self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1)
		fixlevels(self.pullout.frame, self.pullout.frame:GetChildren())

		self:SetHeight(44)
		self:SetWidth(200)
		self:SetLabel()
		self:SetPulloutWidth(nil)
		self.list = {}
	end

	-- exported, AceGUI callback
	local function OnRelease(self)
		if self.open then
			self.pullout:Close()
		end
		AceGUI:Release(self.pullout)
		self.pullout = nil

		self:SetText("")
		self:SetDisabled(false)
		self:SetMultiselect(false)

		self.value = nil
		self.list = nil
		self.open = nil
		self.hasClose = nil

		self.frame:ClearAllPoints()
		self.frame:Hide()
	end

	-- exported
	local function SetDisabled(self, disabled)
		self.disabled = disabled
		if disabled then
			self.text:SetTextColor(0.5,0.5,0.5)
			self.button:Disable()
			self.button_cover:Disable()
			self.label:SetTextColor(0.5,0.5,0.5)
		else
			self.button:Enable()
			self.button_cover:Enable()
			self.label:SetTextColor(1,.82,0)
			self.text:SetTextColor(1,1,1)
		end
	end

	-- exported
	local function ClearFocus(self)
		if self.open then
			self.pullout:Close()
		end
	end

	-- exported
	local function SetText(self, text)
		self.text:SetText(text or "")
	end

	-- exported
	local function SetLabel(self, text)
		if text and text ~= "" then
			self.label:SetText(text)
			self.label:Show()
			self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,-14)
			self:SetHeight(40)
			self.alignoffset = 26
		else
			self.label:SetText("")
			self.label:Hide()
			self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,0)
			self:SetHeight(26)
			self.alignoffset = 12
		end
	end

	-- exported
	local function SetValue(self, value)
		self:SetText(self.list[value] or "")
		self.value = value
	end

	-- exported
	local function GetValue(self)
		return self.value
	end

	-- exported
	local function SetItemValue(self, item, value)
		if not self.multiselect then return end
		for i, widget in self.pullout:IterateItems() do
			if widget.userdata.value == item then
				if widget.SetValue then
					widget:SetValue(value)
				end
			end
		end
		ShowMultiText(self)
	end

	-- exported
	local function SetItemDisabled(self, item, disabled)
		for i, widget in self.pullout:IterateItems() do
			if widget.userdata.value == item then
				widget:SetDisabled(disabled)
			end
		end
	end

	local function AddListItem(self, value, text, itemType)
		if not itemType then itemType = "Dropdown-Item-Toggle" end
		local exists = AceGUI:GetWidgetVersion(itemType)
		if not exists then error(("The given item type, %q, does not exist within AceGUI-3.0"):format(tostring(itemType)), 2) end

		local item = AceGUI:Create(itemType)
		item:SetText(text)
		item.userdata.obj = self
		item.userdata.value = value
		item:SetCallback("OnValueChanged", OnItemValueChanged)
		self.pullout:AddItem(item)
	end

	local function AddCloseButton(self)
		if not self.hasClose then
			local close = AceGUI:Create("Dropdown-Item-Execute")
			close:SetText(CLOSE)
			self.pullout:AddItem(close)
			self.hasClose = true
		end
	end

	-- exported
	local sortlist = {}
	local function sortTbl(x,y)
		local num1, num2 = tonumber(x), tonumber(y)
		if num1 and num2 then -- numeric comparison, either two numbers or numeric strings
			return num1 < num2
		else -- compare everything else tostring'ed
			return tostring(x) < tostring(y)
		end
	end
	local function SetList(self, list, order, itemType)
		self.list = list or {}
		self.pullout:Clear()
		self.hasClose = nil
		if not list then return end

		if type(order) ~= "table" then
			for v in pairs(list) do
				sortlist[#sortlist + 1] = v
			end
			tsort(sortlist, sortTbl)

			for i, key in ipairs(sortlist) do
				AddListItem(self, key, list[key], itemType)
				sortlist[i] = nil
			end
		else
			for i, key in ipairs(order) do
				AddListItem(self, key, list[key], itemType)
			end
		end
		if self.multiselect then
			ShowMultiText(self)
			AddCloseButton(self)
		end
	end

	-- exported
	local function AddItem(self, value, text, itemType)
		self.list[value] = text
		AddListItem(self, value, text, itemType)
	end

	-- exported
	local function SetMultiselect(self, multi)
		self.multiselect = multi
		if multi then
			ShowMultiText(self)
			AddCloseButton(self)
		end
	end

	-- exported
	local function GetMultiselect(self)
		return self.multiselect
	end

	local function SetPulloutWidth(self, width)
		self.pulloutWidth = width
	end

	--[[ Constructor ]]--

	local function Constructor()
		local count = AceGUI:GetNextWidgetNum(widgetType)
		local frame = CreateFrame("Frame", nil, UIParent)
		local dropdown = CreateFrame("Frame", "AceGUI30DropDown"..count, frame, "UIDropDownMenuTemplate")

		local self = {}
		self.type = widgetType
		self.frame = frame
		self.dropdown = dropdown
		self.count = count
		frame.obj = self
		dropdown.obj = self

		self.OnRelease   = OnRelease
		self.OnAcquire   = OnAcquire

		self.ClearFocus  = ClearFocus

		self.SetText     = SetText
		self.SetValue    = SetValue
		self.GetValue    = GetValue
		self.SetList     = SetList
		self.SetLabel    = SetLabel
		self.SetDisabled = SetDisabled
		self.AddItem     = AddItem
		self.SetMultiselect = SetMultiselect
		self.GetMultiselect = GetMultiselect
		self.SetItemValue = SetItemValue
		self.SetItemDisabled = SetItemDisabled
		self.SetPulloutWidth = SetPulloutWidth

		self.alignoffset = 26

		frame:SetScript("OnHide",Dropdown_OnHide)

		dropdown:ClearAllPoints()
		dropdown:SetPoint("TOPLEFT",frame,"TOPLEFT",-15,0)
		dropdown:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",17,0)
		dropdown:SetScript("OnHide", nil)

		local left = _G[dropdown:GetName() .. "Left"]
		local middle = _G[dropdown:GetName() .. "Middle"]
		local right = _G[dropdown:GetName() .. "Right"]

		middle:ClearAllPoints()
		right:ClearAllPoints()

		middle:SetPoint("LEFT", left, "RIGHT", 0, 0)
		middle:SetPoint("RIGHT", right, "LEFT", 0, 0)
		right:SetPoint("TOPRIGHT", dropdown, "TOPRIGHT", 0, 17)

		local button = _G[dropdown:GetName() .. "Button"]
		self.button = button
		button.obj = self
		button:SetScript("OnEnter",Control_OnEnter)
		button:SetScript("OnLeave",Control_OnLeave)
		button:SetScript("OnClick",Dropdown_TogglePullout)

		local button_cover = CreateFrame("BUTTON",nil,self.frame)
		self.button_cover = button_cover
		button_cover.obj = self
		button_cover:SetPoint("TOPLEFT",self.frame,"BOTTOMLEFT",0,25)
		button_cover:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT")
		button_cover:SetScript("OnEnter",Control_OnEnter)
		button_cover:SetScript("OnLeave",Control_OnLeave)
		button_cover:SetScript("OnClick",Dropdown_TogglePullout)

		local text = _G[dropdown:GetName() .. "Text"]
		self.text = text
		text.obj = self
		text:ClearAllPoints()
		text:SetPoint("RIGHT", right, "RIGHT" ,-43, 2)
		text:SetPoint("LEFT", left, "LEFT", 25, 2)

		local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
		label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
		label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
		label:SetJustifyH("LEFT")
		label:SetHeight(18)
		label:Hide()
		self.label = label

		AceGUI:RegisterAsWidget(self)
		return self
	end

	AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
end
