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.
187 lines
8.0 KiB
187 lines
8.0 KiB
local _,rematch = ...
|
|
local L = rematch.localization
|
|
local C = rematch.constants
|
|
rematch.dropdown = {}
|
|
|
|
--[[
|
|
|
|
RematchDropDownTemplate is a dropdown template that's 24px high and any width. The dropdown choices are
|
|
presented in a Rematch-generated menu (see menus\menus.lua) that can be managed automatically by the dropdown
|
|
if the BasicSetup is used or with full control by the menu functions.
|
|
|
|
BasicSetup use:
|
|
|
|
-- creates a dropdown with three options ("One","Two","Etc") and prints the numerical value of the option when chosen
|
|
local dropdown = CreateFrame("Button", nil, UIParent, "RematchDropDownTemplate")
|
|
dropdown:BasicSetup({{text="One",value=1}, {text="Two",value=2}, {text="Etc",value=0}},
|
|
function(value) print(value,"chosen") end)
|
|
|
|
Note: In BasicSetup, EVERY menu item must have a text (displayed in menu/dropdown) and a value (arbitrary value
|
|
associated with the text.) Highlighting is already handled and the function to run when an option is chosen
|
|
is the second parameter of BasicSetup, taking the chosen value as its only argument. icon/iconCoords and
|
|
tooltipTitle/Body are supported.
|
|
If dropdown.forComboBox is true, then menu highlight matches entered text instead of value
|
|
|
|
When more control is needed (such as submenus or non-option choices available), this is the equivalent of above:
|
|
|
|
local dropdown = CreateFrame("Button", nil, UIParent, "RematchDropDownTemplate")
|
|
dropdown.value = 1
|
|
local function showHighlight(self)
|
|
return self.value == dropdown.value
|
|
end
|
|
local function onSelection(self)
|
|
dropdown.value = self.value
|
|
print(self.value,"chosen")
|
|
end
|
|
local menu = {
|
|
{text="One", value=1, highlight=showHighlight, func=onSelection},
|
|
{text="Two", value=2, highlight=showHighlight, func=onSelection},
|
|
{text="Etc", value=0, highlight=showHighlight, func=onSelection}
|
|
}
|
|
dropdown:SetMenu(menu)
|
|
dropdown:SetSelection("value",1)
|
|
|
|
]]
|
|
|
|
local currentMenuID = 1 -- each menu gets a unique identifier, used for the name "DropDownMenu"..currentMenuID
|
|
|
|
--[[ local functions ]]
|
|
|
|
-- fetches the menu's table associated with the dropdown (self)
|
|
local function getMenu(self)
|
|
return rematch.menus:GetDefinition(self.menuName)
|
|
end
|
|
|
|
-- sets the text (and optionally icon) to display in the dropdown; iconCoords (optional too) is an ordered
|
|
-- list of SetTexCoord values (left,right,top,bottom)
|
|
local function setDropDownText(self,text,icon,iconCoords)
|
|
self.Text:SetText(text)
|
|
if icon then
|
|
self.Text:SetPoint("TOPLEFT",23,0)
|
|
self.Icon:SetTexture(icon)
|
|
if iconCoords then
|
|
self.Icon:SetTexCoord(iconCoords[1],iconCoords[2],iconCoords[3],iconCoords[4])
|
|
else -- like menu, no iconCoords means it will trim slightly in to cut off icon border
|
|
self.Icon:SetTexCoord(0.075,0.925,0.075,0.925)
|
|
end
|
|
self.Icon:Show()
|
|
else
|
|
self.Text:SetPoint("TOPLEFT",self.forComboBox and 6 or 8,0)
|
|
self.Icon:Hide()
|
|
end
|
|
end
|
|
|
|
-- this is a postFunc added to all menu items, to update the dropdown's displayed text/icon and set the
|
|
-- selectedValue for basic dropdowns; self is the info of the menu item and subject is the dropdown itself
|
|
local function postMenuItemOnClick(self,subject)
|
|
setDropDownText(subject,self.text,self.icon,self.iconCoords)
|
|
subject.selectedValue = self.value
|
|
end
|
|
|
|
--[[ mixin ]]
|
|
|
|
RematchDropDownMixin = {}
|
|
|
|
-- sets up basic dropdown behavior:
|
|
-- info = {{text="option 1",value="opt1",icon="path\texture1.blp",iconCoords={left,right,top,bottom},tooltipTitle="etc",tooltipBody="etc"},
|
|
-- {text="option 2",value="opt2",icon="path\texture2.blp",iconCoords={left,right,top,bottom}}, etc}
|
|
-- func = function(dropdown,chosen value)
|
|
function RematchDropDownMixin:BasicSetup(menu,func)
|
|
local dropdown = self -- for referencing within menu functions (where self is the info of the chosen selection
|
|
-- build menu and functions from the given info and func
|
|
local function dropdownFunc(self) if func then func(self.value) end end -- passes only the chosen value to func in second parameter
|
|
local function dropdownHighlight(self)
|
|
if dropdown.forComboBox then -- for comboboxes, highlight matching text
|
|
return self.text==dropdown.Text:GetText()
|
|
else -- for normal dropdowns, highlight matching value
|
|
return self.value==dropdown.selectedValue
|
|
end
|
|
end -- highlight selectedValue
|
|
for i,info in ipairs(menu) do
|
|
assert(info.value and info.text,"All dropdown menu entries must have a value and text. See templates\\dropdown.lua.")
|
|
info.func = dropdownFunc
|
|
info.highlight = dropdownHighlight
|
|
if i==1 then
|
|
self.selectedValue = info.value -- pickup first value as default
|
|
end
|
|
end
|
|
|
|
self:SetMenu(menu)
|
|
self:SetSelection("value",self.selectedValue)
|
|
|
|
end
|
|
|
|
-- sets the menu to the dropdown that will appear when the dropdown is clicked
|
|
function RematchDropDownMixin:SetMenu(menu)
|
|
if not self.menuName then -- first time registering a menu, create a new name
|
|
self.menuName = format("DropDownMenu%d",rematch.utils:GetNewMenuID())
|
|
end
|
|
for _,menuItem in ipairs(menu) do
|
|
menuItem.postFunc = postMenuItemOnClick
|
|
end
|
|
rematch.menus:Register(self.menuName,menu)
|
|
end
|
|
|
|
-- sets the text/icon displayed in the dropdown to the choice where the given key is the given value; for instance
|
|
-- a {anchor="BOTTOMRIGHT",etc=..} will select this with SetSelection("anchor","BOTTOMRIGHT")
|
|
-- if no second parameter is given, then it will assume this is a "value" key for basic dropdowns
|
|
function RematchDropDownMixin:SetSelection(key,value)
|
|
if value==nil then -- this is likely a basic dropdown where the key is "value"
|
|
value = key
|
|
key = "value"
|
|
end
|
|
if self.menuName then
|
|
local menu = getMenu(self)
|
|
for _,info in ipairs(menu) do
|
|
if info[key]==value then
|
|
self.selectedValue = value
|
|
setDropDownText(self,info.text,info.icon,info.iconCoords)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
-- if we reached here, there was an attempt to set to a value that doesn't exist, throw an exception
|
|
assert(false,"value '"..(value or "nil").."' doesn't exist for '"..(key or "nil").."' in dropdown menu")
|
|
end
|
|
|
|
-- returns the currently selected value
|
|
function RematchDropDownMixin:GetSelection()
|
|
return self.selectedValue
|
|
end
|
|
|
|
function RematchDropDownMixin:OnEnter()
|
|
rematch.textureHighlight:Show(self.DropDownButton,self.Left,self.Right,self.Middle)
|
|
end
|
|
|
|
function RematchDropDownMixin:OnLeave()
|
|
rematch.textureHighlight:Hide()
|
|
end
|
|
|
|
function RematchDropDownMixin:OnMouseDown()
|
|
rematch.textureHighlight:Hide()
|
|
end
|
|
|
|
function RematchDropDownMixin:OnMouseUp()
|
|
if GetMouseFocus()==self then
|
|
rematch.textureHighlight:Show(self.DropDownButton,self.Left,self.Right,self.Middle)
|
|
end
|
|
end
|
|
|
|
-- called when the dropdown is clicked (the right button is highlighted but the whole dropdown box counts for clicks)
|
|
-- it toggles a menu just beneath the control that's at least as wide as the dropdown
|
|
function RematchDropDownMixin:OnClick(button)
|
|
if self.menuName then
|
|
local menu = getMenu(self)
|
|
if menu and menu[1] then -- make menu width be at least dropdown's width
|
|
menu[1].minWidth = self:GetWidth()-(C.MENU_FRAME_PADDING*2)
|
|
end
|
|
-- one of the self parameter is the subject, the dropdown itself; so PostMenuItemClick can use it
|
|
rematch.menus:Toggle(self.menuName,self,self,"TOPRIGHT",self,"BOTTOMRIGHT",0,2)
|
|
PlaySound(C.SOUND_CHECKBUTTON)
|
|
end
|
|
end
|
|
|
|
-- if dropdown hidden by a collapsing header or other reason, menu attached to it should hide too
|
|
function RematchDropDownMixin:OnHide()
|
|
rematch.menus:Hide()
|
|
end
|
|
|