You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

248 lines
7.5 KiB

if not WeakAuras.IsCorrectVersion() then return end
local Type, Version = "WeakAurasTwoColumnDropdown", 3
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
local function errorhandler(err)
return geterrorhandler()(err)
end
local function safecall(func, ...)
if func then
return xpcall(func, errorhandler, ...)
end
end
AceGUI:RegisterLayout("TwoColumn",
function(content, children)
local height = 0
local width = content.width or content:GetWidth() or 0
for i = 1, #children do
local child = children[i]
local frame = child.frame
frame:ClearAllPoints()
if child.userdata.hideMe then
frame:Hide()
else
frame:Show()
end
if i == 1 then
frame:SetPoint("TOPLEFT", content)
else
frame:SetPoint("TOPLEFT", children[i-1].frame, "TOPRIGHT")
end
if child.width == "relative" then
child:SetWidth(width * child.relWidth)
if child.DoLayout then
child:DoLayout()
end
end
height = max(height, frame.height or frame:GetHeight() or 0)
end
safecall(content.obj.LayoutFinished, content.obj, nil, height)
end)
local methods = {
["OnAcquire"] = function(widget)
local firstDropdown = AceGUI:Create("Dropdown")
local secondDropDown = AceGUI:Create("Dropdown")
firstDropdown:SetRelativeWidth(0.5)
firstDropdown:SetPulloutWidth(200)
secondDropDown:SetRelativeWidth(0.5)
secondDropDown:SetLabel(" ")
secondDropDown:SetPulloutWidth(200)
secondDropDown.userdata.defaultSelection = {}
widget.firstDropdown = firstDropdown
widget.secondDropDown = secondDropDown
widget:SetLayout("TwoColumn")
widget.SetLayout = function()
-- AceGui wants to set a default layout, but we don't want that
end
widget:AddChild(firstDropdown)
widget:AddChild(secondDropDown)
local OnFirstDropdownValueChanged = function(self, event, value)
local displayName = widget.userdata.firstList[value]
local treeValue = widget.userdata.tree[displayName]
if type(treeValue) == "table" then
local oldValue
if widget.userdata.secondList then
local v = widget.secondDropDown:GetValue()
if v then
oldValue = widget.userdata.secondList[v]
end
end
local secondList = {}
for displayName, _ in pairs(treeValue) do
tinsert(secondList, displayName)
end
table.sort(secondList)
local oldValueIndex = tIndexOf(secondList, oldValue)
widget.userdata.secondList = secondList
widget.secondDropDown:SetList(secondList)
widget.firstDropdown:SetRelativeWidth(0.5)
widget.secondDropDown:SetRelativeWidth(0.5)
widget.secondDropDown.userdata.hideMe = false
widget:DoLayout()
if (oldValueIndex) then
widget.secondDropDown:SetValue(oldValueIndex)
local v = widget:GetValue()
if (v) then
widget:Fire("OnValueChanged", v)
end
else
local default = widget.secondDropDown.userdata.defaultSelection[displayName]
if default then
local index = tIndexOf(secondList, default)
widget.secondDropDown:SetValue(index)
local v = widget:GetValue()
if (v) then
widget:Fire("OnValueChanged", v)
end
else
widget.secondDropDown:SetValue()
end
end
else
widget.firstDropdown:SetRelativeWidth(1)
widget.secondDropDown.userdata.hideMe = true
widget.userdata.secondList = nil
widget:DoLayout()
widget:Fire("OnValueChanged", treeValue)
end
end
firstDropdown.OnFirstDropdownValueChanged = OnFirstDropdownValueChanged
local OnSecondDropdownValueChanged = function(self, event, value)
widget:Fire("OnValueChanged", widget:GetValue())
end
firstDropdown:SetCallback("OnValueChanged", OnFirstDropdownValueChanged)
secondDropDown:SetCallback("OnValueChanged", OnSecondDropdownValueChanged)
local function FireOnEnter(self, event)
widget:Fire("OnEnter")
end
local function FireOnLeave(self, event)
widget:Fire("OnLeave")
end
firstDropdown:SetCallback("OnEnter", FireOnEnter)
firstDropdown:SetCallback("OnLeave", FireOnLeave)
secondDropDown:SetCallback("OnEnter", FireOnEnter)
secondDropDown:SetCallback("OnLeave", FireOnLeave)
end,
["OnRelease"] = function(self)
end,
["SetLabel"] = function(self, ...)
self.firstDropdown:SetLabel(...)
end,
["SetValue"] = function(self, value)
for displayName, treeValue in pairs(self.userdata.tree) do
if treeValue == value then
self.firstDropdown:SetRelativeWidth(1)
self.secondDropDown.userdata.hideMe = true
self:DoLayout()
self.firstDropdown:SetValue(tIndexOf(self.userdata.firstList, displayName))
return
elseif type(treeValue) == "table" then
for displayName2, key in pairs(treeValue) do
if (key == value) then
self.firstDropdown:SetRelativeWidth(0.5)
self.secondDropDown:SetRelativeWidth(0.5)
self.secondDropDown.userdata.hideMe = false
self:DoLayout()
local index = tIndexOf(self.userdata.firstList, displayName);
self.firstDropdown:SetValue(index)
self.firstDropdown:OnFirstDropdownValueChanged("", index)
self.secondDropDown:SetValue(tIndexOf(self.userdata.secondList, displayName2))
return
end
end
end
end
self.firstDropdown:SetRelativeWidth(1)
self.secondDropDown.userdata.hideMe = true
self:DoLayout()
self.firstDropdown:SetValue(nil)
end,
["GetValue"] = function(self)
local displayName1 = self.userdata.firstList[self.firstDropdown:GetValue()]
local treeValue = self.userdata.tree[displayName1]
if not treeValue then
return nil
end
if type(treeValue) ~= "table" then
return treeValue
end
local displayName2 = self.userdata.secondList[self.secondDropDown:GetValue()]
treeValue = treeValue[displayName2]
if not treeValue then
return nil
end
return treeValue
end,
["SetList"] = function(self, list, order, itemType)
local tree = {}
for key, displayName in pairs(list) do
if type(displayName) == "table" then
local base = displayName[1]
local suffix = displayName[2]
tree[base] = tree[base] or {}
tree[base][suffix] = key
if displayName[3] == true then
self.secondDropDown.userdata.defaultSelection[base] = suffix
end
else
tree[displayName] = key
end
end
self.userdata.tree = tree
local firstList = {}
for displayName, _ in pairs(tree) do
tinsert(firstList, displayName)
end
table.sort(firstList)
self.userdata.firstList = firstList
self.firstDropdown:SetList(firstList, order, itemType)
end
}
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:SetHeight(50)
frame:SetWidth(50)
local content = CreateFrame("Frame", nil, frame)
content:SetPoint("TOPLEFT", 0, 0)
content:SetPoint("BOTTOMRIGHT", 0, 0)
local widget = {
frame = frame,
content = content,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
return AceGUI:RegisterAsContainer(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)