Apply Patch
This commit is contained in:
@@ -0,0 +1,342 @@
|
||||
-- This can either be used as a normal dropdown or a context menu. If the parent is UIParent, it will be a context menu.
|
||||
-- Otherwise, it is a dropdown. This can be changed during runtime simply by calling SetParent through the GUI component.
|
||||
-- The positioning of the dropdown's components are modified to behave like you'd expect. SetWidth actually sets the width.
|
||||
-- SetHeight does nothing, and will always be 25 px.
|
||||
|
||||
-- Initialization is handled by this component. Use SetOptions to set the options table.
|
||||
-- === New Fields ===
|
||||
-- initFunc(self, gui) - Runs on level initialization before the button is added
|
||||
-- dropdownText - The text the dropdown will be set to when this option is clicked, runs before "func"
|
||||
-- closeOnClick - If true, closes all menus regardless of level, runs after "func"
|
||||
-- children - Array for a next level menu; If present, "hasArrow" is automatically set to true
|
||||
-- parent [Automatically Assigned] - Reference to the previous level element, or nil if root
|
||||
-- siblings [Automatically Assigned] - Reference to the array of elements in the level
|
||||
-- gui [Automatically Assigned] - Reference to the GUI instance
|
||||
-- === Adjusted Existing Fields ===
|
||||
-- func(self, gui) - Always passes self as the first argument and the GUI instance as the second argument
|
||||
-- arg1, arg2 - Do not use, now internally used to pass self and gui to "func"
|
||||
-- value - Do not use, now internally used to reference self
|
||||
|
||||
PTGuiDropdown = PTGuiComponent:Extend("dropdown")
|
||||
local _G = getfenv(0)
|
||||
local compost = PTPool
|
||||
|
||||
PTGuiDropdown.Options = nil
|
||||
|
||||
function PTGuiDropdown:New()
|
||||
local obj = setmetatable({}, self)
|
||||
local dropdown = CreateFrame("Frame", self:GenerateName(), nil, "UIDropDownMenuTemplate")
|
||||
obj:SetHandle(dropdown)
|
||||
-- Make SetWidth actually set the width, like one would hope
|
||||
local dropdownSetWidth = dropdown.SetWidth
|
||||
dropdownSetWidth(dropdown, 0) -- Allows points to size the dropdown
|
||||
dropdown.SetWidth = function(self, width)
|
||||
_G[dropdown:GetName().."Middle"]:SetWidth(width - 15)
|
||||
dropdownSetWidth(self, width)
|
||||
_G[dropdown:GetName().."Text"]:SetWidth(width - 25)
|
||||
dropdown.noResize = 1
|
||||
end
|
||||
-- The dropdown doesn't stretch vertically, so the height is always 25
|
||||
local dropdownSetHeight = dropdown.SetHeight
|
||||
dropdown.SetHeight = function(self, height)
|
||||
dropdownSetHeight(self, 25)
|
||||
end
|
||||
obj:SetShowShadow(true) -- Need to do this on creation to fix the visual position
|
||||
-- Make clicking anywhere on the dropdown open the menu
|
||||
dropdown:EnableMouse(true)
|
||||
dropdown:SetScript("OnMouseUp", function()
|
||||
if MouseIsOver(this) then
|
||||
PTUtil.CallWithThis(_G[this:GetName().."Button"], _G[this:GetName().."Button"]:GetScript("OnClick"))
|
||||
end
|
||||
end)
|
||||
dropdown:SetScript("OnSizeChanged", function()
|
||||
local width = this:GetWidth()
|
||||
_G[this:GetName().."Middle"]:SetWidth(width - 15)
|
||||
dropdownSetWidth(this, width)
|
||||
_G[this:GetName().."Text"]:SetWidth(width - 25)
|
||||
end)
|
||||
return obj
|
||||
end
|
||||
|
||||
local partProps = {
|
||||
Default = {
|
||||
Left = {
|
||||
Width = 25, Height = 64,
|
||||
Coords = {0, 0.1953125, 0, 1},
|
||||
Point = {"TOPLEFT", "$parent", "TOPLEFT", -18, 18}
|
||||
},
|
||||
Middle = {
|
||||
Width = 115, Height = 64,
|
||||
Coords = {0.1953125, 0.8046875, 0, 1},
|
||||
Point = {"LEFT", "$parentLeft", "RIGHT"}
|
||||
},
|
||||
Right = {
|
||||
Width = 25, Height = 64,
|
||||
Coords = {0.8046875, 1, 0, 1},
|
||||
Point = {"LEFT", "$parentMiddle", "RIGHT"}
|
||||
},
|
||||
Text = {
|
||||
Point = {"RIGHT", "$parentRight", -43, 2}
|
||||
},
|
||||
Button = {
|
||||
Point = {"TOPRIGHT", "$parentRight", -16, -18}
|
||||
}
|
||||
},
|
||||
Shadowless = {
|
||||
Left = {
|
||||
Width = 6, Height = 24,
|
||||
Coords = {18 / 128, (18 + 6) / 128, 19 / 64, (19 + 24) / 64},
|
||||
Point = {"TOPLEFT", 0, -1}
|
||||
},
|
||||
Middle = {
|
||||
Width = 115, Height = 24,
|
||||
Coords = {0.1953125, 0.8046875, 19 / 64, (19 + 24) / 64},
|
||||
Point = {"LEFT", "$parentLeft", "RIGHT", 0, 0}
|
||||
},
|
||||
Right = {
|
||||
Width = 9, Height = 24,
|
||||
Coords = {102 / 128, (102 + 9) / 128, 19 / 64, (19 + 24) / 64},
|
||||
Point = {"LEFT", "$parentMiddle", "RIGHT", 0, 0}
|
||||
},
|
||||
Text = {
|
||||
Point = {"RIGHT", "$parentRight", -26, 1}
|
||||
},
|
||||
Button = {
|
||||
Point = {"TOPRIGHT", "$parentRight", 1, 1}
|
||||
}
|
||||
}
|
||||
}
|
||||
function PTGuiDropdown:SetShowShadow(showShadow)
|
||||
local frameName = self:GetHandle():GetName()
|
||||
for partName, props in pairs(showShadow and partProps.Default or partProps.Shadowless) do
|
||||
local part = _G[frameName..partName]
|
||||
if props.Coords then
|
||||
part:SetTexCoord(unpack(props.Coords))
|
||||
end
|
||||
if props.Width then
|
||||
part:SetWidth(props.Width)
|
||||
part:SetHeight(props.Height)
|
||||
end
|
||||
part:ClearAllPoints()
|
||||
part:SetPoint(unpack(props.Point))
|
||||
end
|
||||
self:SetWidth(self:GetWidth())
|
||||
UIDropDownMenu_SetAnchor(showShadow and 18 or 0, showShadow and 17 or 0, self:GetHandle(), "TOPLEFT",
|
||||
_G[frameName.."Left"], "BOTTOMLEFT")
|
||||
return self
|
||||
end
|
||||
|
||||
local defaultTextures = {
|
||||
ButtonNormalTexture = "Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Up",
|
||||
ButtonDisabledTexture = "Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Disabled",
|
||||
ButtonPushedTexture = "Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Down",
|
||||
ButtonHighlightTexture = "Interface\\Buttons\\UI-Common-MouseHilight"
|
||||
}
|
||||
function PTGuiDropdown:SetParent(obj)
|
||||
local menuType = obj == UIParent and "MENU" or nil
|
||||
if menuType ~= "MENU" and self:GetHandle().displayMode == "MENU" then
|
||||
-- Show the dropdown if we're switching from a context menu to a dropdown
|
||||
-- BROKEN: When put back as a context menu, the button shows forever???
|
||||
local frameName = self:GetHandle():GetName()
|
||||
_G[frameName.."Left"]:Show()
|
||||
_G[frameName.."Middle"]:Show()
|
||||
_G[frameName.."Right"]:Show()
|
||||
for texName, texPath in pairs(defaultTextures) do
|
||||
_G[frameName..texName]:SetTexture(texPath)
|
||||
end
|
||||
self:SetShowShadow(true)
|
||||
self:GetHandle().displayMode = nil
|
||||
end
|
||||
UIDropDownMenu_Initialize(self:GetHandle(), function(level)
|
||||
self:Initialize(level)
|
||||
end, menuType)
|
||||
self.super.SetParent(self, obj)
|
||||
end
|
||||
|
||||
function PTGuiDropdown:OnDispose()
|
||||
self:SetToggleState(false)
|
||||
self:SetShowShadow(true)
|
||||
self.super.OnDispose(self)
|
||||
|
||||
self.Options = nil
|
||||
if self.DynamicOptions then
|
||||
compost:Reclaim(self.DynamicOptions, 1)
|
||||
self.DynamicOptionsArgs = nil
|
||||
end
|
||||
self.TextUpdater = nil
|
||||
self:SetText("")
|
||||
end
|
||||
|
||||
local dynamicOptions
|
||||
local function addDynamicOption(k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
|
||||
local option = compost:AcquireHash(k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
|
||||
table.insert(dynamicOptions, option)
|
||||
end
|
||||
|
||||
function PTGuiDropdown:Initialize(level)
|
||||
if not self.Options then
|
||||
return
|
||||
end
|
||||
level = level or 1
|
||||
local options = self.Options
|
||||
if type(options) == "function" then
|
||||
if self.DynamicOptions then
|
||||
compost:Reclaim(self.DynamicOptions, 1)
|
||||
end
|
||||
self.DynamicOptions = compost:GetTable()
|
||||
dynamicOptions = self.DynamicOptions
|
||||
options(addDynamicOption, level, self.DynamicOptionsArgs)
|
||||
options = dynamicOptions
|
||||
self:BakeOptions(options)
|
||||
end
|
||||
local value = UIDROPDOWNMENU_MENU_VALUE
|
||||
options = level == 1 and options or value.children
|
||||
for _, option in ipairs(options) do
|
||||
if option.initFunc then
|
||||
option:initFunc(self)
|
||||
end
|
||||
UIDropDownMenu_AddButton(option, level)
|
||||
end
|
||||
end
|
||||
|
||||
-- Similar to normal dropdown initialization. Really only should be used for single level options.
|
||||
-- The initFunc receives a function to add options, use in the style of Compost:AcquireHash
|
||||
-- args are passed into the initFunc
|
||||
function PTGuiDropdown:SetDynamicOptions(initFunc, args)
|
||||
self.Options = initFunc
|
||||
self.DynamicOptionsArgs = args
|
||||
return self
|
||||
end
|
||||
|
||||
function PTGuiDropdown:SetSimpleOptions(options, createFunc, dropdownText)
|
||||
local optTable = {}
|
||||
for _, option in ipairs(options) do
|
||||
table.insert(optTable, createFunc(option))
|
||||
end
|
||||
self:SetOptions(optTable)
|
||||
if dropdownText then
|
||||
self:SetText(dropdownText)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
-- Sets the options for this dropdown. If elements are added afterwards, it is mandatory that this function is called again.
|
||||
function PTGuiDropdown:SetOptions(options)
|
||||
self.Options = options
|
||||
self:BakeOptions(options)
|
||||
return self
|
||||
end
|
||||
|
||||
function PTGuiDropdown:BakeOptions(options, parent)
|
||||
for _, opt in ipairs(options) do
|
||||
opt.parent = parent
|
||||
opt.siblings = options
|
||||
opt.value = opt
|
||||
opt.arg1 = opt
|
||||
opt.arg2 = self
|
||||
opt.gui = self
|
||||
if opt.dropdownText or opt.closeOnClick then
|
||||
local func = opt.func
|
||||
opt.func = function(self, gui)
|
||||
if self.dropdownText then
|
||||
gui:SetText(self.dropdownText)
|
||||
end
|
||||
if func then
|
||||
func(self, gui)
|
||||
end
|
||||
if self.closeOnClick then
|
||||
gui:SetToggleState(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
if opt.children then
|
||||
opt.hasArrow = true
|
||||
self:BakeOptions(opt.children, opt)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PTGuiDropdown:SetTextBy(field, value, textField)
|
||||
for _, option in ipairs(self.Options) do
|
||||
if option[field] == value then
|
||||
self:SetText(option[textField or "text"])
|
||||
return self
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function PTGuiDropdown:SetTextUpdater(updater, noImmediateUpdate)
|
||||
self.TextUpdater = updater
|
||||
if not noImmediateUpdate then
|
||||
self:TextUpdater()
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function PTGuiDropdown:UpdateText()
|
||||
if self.TextUpdater then
|
||||
self:TextUpdater()
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function PTGuiDropdown:SetText(text)
|
||||
UIDropDownMenu_SetText(text, self:GetHandle())
|
||||
return self
|
||||
end
|
||||
|
||||
function PTGuiDropdown:GetText()
|
||||
return UIDropDownMenu_GetText(self:GetHandle())
|
||||
end
|
||||
|
||||
local dropdownList1 = _G["DropDownList1"]
|
||||
function PTGuiDropdown:SetTimer(time)
|
||||
dropdownList1.showTimer = time
|
||||
end
|
||||
|
||||
function PTGuiDropdown:StopCounting()
|
||||
dropdownList1.isCounting = nil
|
||||
end
|
||||
|
||||
local keepOpenFrame = CreateFrame("Frame", "PTGuiDropdownKeepOpen")
|
||||
local keepOpenDropdown
|
||||
local checkNext
|
||||
local keepOpenScript = function()
|
||||
if GetTime() > checkNext then
|
||||
if not keepOpenDropdown:IsToggledOn() then
|
||||
keepOpenFrame:SetScript("OnUpdate", nil)
|
||||
return
|
||||
end
|
||||
checkNext = GetTime() + 1
|
||||
dropdownList1.showTimer = 10
|
||||
dropdownList1.isCounting = nil
|
||||
end
|
||||
end
|
||||
-- Keeps the dropdown open until it is forcibly hidden
|
||||
function PTGuiDropdown:SetKeepOpen(keepOpen)
|
||||
if not self:IsToggledOn() then
|
||||
return self
|
||||
end
|
||||
if keepOpen then
|
||||
checkNext = 0
|
||||
keepOpenDropdown = self
|
||||
keepOpenFrame:SetScript("OnUpdate", keepOpenScript)
|
||||
else
|
||||
keepOpenFrame:SetScript("OnUpdate", nil)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function PTGuiDropdown:IsToggledOn()
|
||||
return (dropdownList1:IsVisible() ~= nil) and (UIDROPDOWNMENU_OPEN_MENU == self:GetName())
|
||||
end
|
||||
|
||||
function PTGuiDropdown:SetToggleState(shown, anchor, xOffset, yOffset)
|
||||
if self:IsToggledOn() ~= shown then
|
||||
ToggleDropDownMenu(1, nil, self:GetHandle(), anchor and anchor:GetName() or nil, xOffset, yOffset)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
PTGuiLib.RegisterComponent(PTGuiDropdown)
|
||||
Reference in New Issue
Block a user