Show pfUI's dropdowns and menus with ClassicAPI's menu system

pfUIDropdownTemplate (a DropdownButton) replaces CreateDropDownButton in
the config GUI, addon profiles, the trigger editor and the icon picker
filter. The equipment set gear menu and the tracking menu open
MenuUtil context menus. pfUIMenuStyleMixin draws pfUI's backdrop behind
them, and the skin module makes it the default style and draws the
checkboxes and radios as pfUI boxes.
This commit is contained in:
Brues
2026-10-30 19:33:40 -05:00
parent f37ea00226
commit af9edb215d
7 changed files with 292 additions and 444 deletions
+51 -226
View File
@@ -100,219 +100,53 @@ do -- statusbars
end
end
do -- dropdown
local function ListEntryOnShow()
this.icon:SetShown(this.parent.id == this.id)
-- [ pfUIMenuStyleMixin ]
-- Style for ClassicAPI's menus: pfUI's backdrop behind the entries. A dropdown
-- takes it as its menuMixin, and a context menu takes it from the menuMixin
-- field of its owner.
_G.pfUIMenuStyleMixin = CreateFromMixins(MenuStyleMixin)
-- Menus share pooled frames that clear their backdrop on release, so the
-- backdrop goes on the frame itself.
function pfUIMenuStyleMixin:Generate()
CreateBackdrop(self, nil, true)
end
do
local inset = { left = 4, top = 4, right = 4, bottom = 4 }
function pfUIMenuStyleMixin:GetInset()
return inset
end
local function ListEntryOnClick()
this.parent:SetSelection(this.id)
if this.parent.mode == "MULTISELECT" then
this.parent:ShowMenu()
else
this.parent:HideMenu()
end
if this.parent.menu[this.id].func then
this.parent.menu[this.id].func()
end
-- room for a submenu arrow or a color swatch, as in the stock styles
local padding = { width = 10, height = 0 }
function pfUIMenuStyleMixin:GetChildExtentPadding()
return padding
end
end
local function ListEntryOnEnter()
this.hover:Show()
end
-- [ pfUIDropdownTemplate ]
-- Mixin of the template in ui-widgets.xml: a dropdown that shows its selection
-- as text, with pfUI's arrow box at the right.
_G.pfUIDropdownMixin = CreateFromMixins(ButtonStateBehaviorMixin, DropdownSelectionTextMixin)
local function ListEntryOnLeave()
this.hover:Hide()
end
function pfUIDropdownMixin:OnLoad()
self.Text:SetFont(pfUI.font_default, pfUI_config.global.font_size - 1, "OUTLINE")
CreateBackdrop(self.Arrow, nil, true)
self.Arrow.Icon:SetTexture(pfUI.media["img:down"])
self.Arrow.Icon:SetVertexColor(.8, .8, .8)
self.Arrow.Icon:SetAlpha(.8)
local function ListButtonOnClick()
if this.ToggleMenu then
this:ToggleMenu()
else
this:GetParent():ToggleMenu()
end
end
ButtonStateBehaviorMixin.OnLoad(self)
DropdownSelectionTextMixin.OnLoad(self)
end
local function MenuOnUpdate()
if not this:IsMouseOver(100, -100, -100, 100) then
this.button:HideMenu()
end
end
local function ListButtonOnEnter()
this.button:SetBackdropBorderColor(this.button.cr,this.button.cg,this.button.cb,(this.button.ca or 1))
end
local function ListButtonOnLeave()
this.button:SetBackdropBorderColor(this.button.rr,this.button.rg,this.button.rb,(this.button.ra or 1))
end
local handlers = {
["SetSelection"] = function(self, id)
if id and self.menu and self.menu[id] then
self.text:SetText(self.menu[id].text)
self.id = id
end
end,
["SetSelectionByText"] = function(self, name)
self:UpdateMenu()
for id, entry in pairs(self.menu) do
if entry.text == name then
self:SetSelection(id)
return true
end
end
self.text:SetText(name)
return nil
end,
["GetSelection"] = function(self)
self:UpdateMenu()
if self.menu and self.menu[self.id] then
return self.id, self.menu[self.id].text, self.menu[self.id].func
end
end,
["SetMenu"] = function(self, menu)
if type(menu) == "function" then
self.menu = menu()
self.menufunc = menu
else
self.menu = menu
self.menufunc = nil
end
end,
["GetMenu"] = function(self)
self:UpdateMenu()
return self.menu
end,
["ShowMenu"] = function(self)
self:UpdateMenu()
self.menuframe:SetFrameLevel(self:GetFrameLevel() + 8)
self.menuframe:SetHeight(table.getn(self.menu)*20+4)
self.menuframe:Show()
end,
["HideMenu"] = function(self)
self.menuframe:Hide()
end,
["ToggleMenu"] = function(self)
if self.menuframe:IsShown() then
self:HideMenu()
else
self:ShowMenu()
end
end,
["UpdateMenu"] = function(self)
-- run/reload menu function if available
if self.menufunc then self.menu = self.menufunc() end
if not self.menu then return end
-- set caption to the current value
self.text:SetText(self.menu[self.id] and self.menu[self.id].text or "")
-- refresh menu buttons
for id, element in pairs(self.menuframe.elements) do
element:Hide()
end
for id, data in pairs(self.menu) do
self:CreateMenuEntry(id)
end
end,
["CreateMenuEntry"] = function(self, id)
if not self.menu[id] then return end
local frame, entry
for count, existing in pairs(self.menuframe.elements) do
if not existing:IsShown() then
frame = existing
entry = count
break
end
end
if not frame and not entry then
entry = table.getn(self.menuframe.elements) + 1
frame = CreateFrame("Button", nil, self.menuframe)
frame:SetFrameStrata("FULLSCREEN")
frame:ClearAllPoints()
frame:SetPoint("TOPLEFT", self.menuframe, "TOPLEFT", 2, -(entry-1)*20-2)
frame:SetPoint("TOPRIGHT", self.menuframe, "TOPRIGHT", -2, -(entry-1)*20-2)
frame:SetHeight(20)
frame.parent = self
frame.icon = frame:CreateTexture(nil, "OVERLAY")
frame.icon:SetPoint("RIGHT", frame, "RIGHT", -2, 0)
frame.icon:SetSize(16, 16)
frame.icon:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
frame.text = frame:CreateFontString(nil, "OVERLAY")
frame.text:SetFontObject(GameFontWhite)
frame.text:SetFont(pfUI.font_default, pfUI_config.global.font_size-1, "OUTLINE")
frame.text:SetJustifyH("RIGHT")
frame.text:SetPoint("LEFT", frame, "LEFT", 2, 0)
frame.text:SetPoint("RIGHT", frame.icon, "LEFT", -2, 0)
frame.hover = frame:CreateTexture(nil, "BACKGROUND")
frame.hover:SetAllPoints(frame)
frame.hover:SetTexture(.4,.4,.4,.4)
frame.hover:Hide()
table.insert(self.menuframe.elements, frame)
end
frame.id = id
frame.text:SetText(self.menu[id].text)
frame:SetScript("OnShow", ListEntryOnShow)
frame:SetScript("OnClick", ListEntryOnClick)
frame:SetScript("OnEnter", ListEntryOnEnter)
frame:SetScript("OnLeave", ListEntryOnLeave)
frame:Show()
end,
}
function pfUI.api.CreateDropDownButton(name, parent)
local frame = CreateFrame("Button", name, parent)
frame:SetScript("OnEnter", ListButtonOnEnter)
frame:SetScript("OnLeave", ListButtonOnLeave)
frame:SetScript("OnClick", ListButtonOnClick)
frame:SetHeight(20)
frame.id = nil
CreateBackdrop(frame, nil, true)
local button = CreateFrame("Button", nil, frame)
button:SetPoint("RIGHT", frame, "RIGHT", -2, 0)
button:SetSize(16, 16)
button:SetScript("OnClick", ListButtonOnClick)
SkinArrowButton(button, "down")
button.icon:SetVertexColor(1,.9,.1)
local text = frame:CreateFontString(nil, "OVERLAY")
text:SetFontObject(GameFontWhite)
text:SetFont(pfUI.font_default, pfUI_config.global.font_size-1, "OUTLINE")
text:SetPoint("RIGHT", button, "LEFT", -4, 0)
text:SetJustifyH("RIGHT")
local menuframe = CreateFrame("Frame", tostring(frame).."menu", parent)
menuframe.button = frame
menuframe.elements = {}
menuframe:SetPoint("TOPLEFT", frame, "BOTTOMLEFT", 0, -2)
menuframe:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, 2)
menuframe:SetScript("OnUpdate", MenuOnUpdate)
menuframe:Hide()
CreateBackdrop(menuframe, nil, true)
for name, func in pairs(handlers) do
frame[name] = func
end
frame.menuframe = menuframe
frame.button = button
frame.text = text
return frame
-- the arrow box takes the class color while the cursor is over the dropdown
function pfUIDropdownMixin:OnButtonStateChanged()
if self:IsOver() then
self.Arrow:SetBackdropBorderColor(PFUI_CLASS_COLORS[UnitClassBase("player")]:GetRGB())
else
self.Arrow:SetBackdropBorderColor(GetStringColor(pfUI_config.appearance.border.color))
end
end
@@ -1149,11 +983,11 @@ function pfUI.api.CreateIconPicker(name, parent, extraType, nameLabelText)
grid:SetSize(gridWidth + 4 + 7 + 10, gridHeight + 10)
-- Filter dropdown: All / Spells / Items
local filterDropdown = CreateFrame("Frame", name.."Filter", parent, "UIDropDownMenuTemplate")
filterDropdown:SetPoint("TOPRIGHT", parent, "TOPRIGHT", 0, -80)
local function IsFilter(value)
return currentFilter == value
end
local function ApplyFilter(value)
currentFilter = value
UIDropDownMenu_SetSelectedValue(filterDropdown, value)
if provider then
if value == "spells" then provider:SetIconTypes({ IconDataProviderIconType.Spell })
elseif value == "items" then provider:SetIconTypes({ IconDataProviderIconType.Item })
@@ -1162,24 +996,15 @@ function pfUI.api.CreateIconPicker(name, parent, extraType, nameLabelText)
RefreshIconGrid()
end
end
UIDropDownMenu_Initialize(filterDropdown, function()
local info
info = {}; info.text = ICON_FILTER_ALL; info.value = "all"
info.func = function() ApplyFilter("all") end
info.checked = currentFilter == "all"
UIDropDownMenu_AddButton(info)
info = {}; info.text = ICON_FILTER_SPELL; info.value = "spells"
info.func = function() ApplyFilter("spells") end
info.checked = currentFilter == "spells"
UIDropDownMenu_AddButton(info)
info = {}; info.text = ICON_FILTER_ITEM; info.value = "items"
info.func = function() ApplyFilter("items") end
info.checked = currentFilter == "items"
UIDropDownMenu_AddButton(info)
local filterDropdown = CreateFrame("DropdownButton", nil, parent, "pfUIDropdownTemplate")
filterDropdown:SetPoint("TOPRIGHT", parent, "TOPRIGHT", -14, -84)
filterDropdown:SetWidth(140)
CreateBackdrop(filterDropdown, nil, true)
filterDropdown:SetupMenu(function(dropdown, rootDescription)
rootDescription:CreateRadio(ICON_FILTER_ALL, IsFilter, ApplyFilter, "all")
rootDescription:CreateRadio(ICON_FILTER_SPELL, IsFilter, ApplyFilter, "spells")
rootDescription:CreateRadio(ICON_FILTER_ITEM, IsFilter, ApplyFilter, "items")
end)
UIDropDownMenu_SetWidth(120, filterDropdown)
UIDropDownMenu_SetSelectedValue(filterDropdown, "all")
SkinDropDown(filterDropdown)
-- the selected icon gets a gold border in the grid and shows in the preview
local function UpdateSelection()
+48
View File
@@ -102,4 +102,52 @@
<OnLoad method="InitScrollBar" inherit="prepend"/>
</Scripts>
</Frame>
<!--
A ClassicAPI dropdown in pfUI's style: the selection as right-aligned text
and pfUI's arrow box at the right. Its menu takes pfUIMenuStyleMixin. Fill it
with dropdown:SetupMenu(function(dropdown, rootDescription) ... end), and call
dropdown:GenerateMenu() when the data behind the selection changes.
-->
<DropdownButton name="pfUIDropdownTemplate" mixin="pfUIDropdownMixin" virtual="true">
<Size y="20"/>
<KeyValues>
<KeyValue key="menuMixin" value="pfUIMenuStyleMixin" type="global"/>
<KeyValue key="menuPointY" value="-2" type="number"/>
</KeyValues>
<Frames>
<Frame parentKey="Arrow">
<Size x="16" y="16"/>
<Anchors>
<Anchor point="RIGHT" x="-2"/>
</Anchors>
<Layers>
<Layer level="ARTWORK">
<Texture parentKey="Icon">
<Anchors>
<Anchor point="TOPLEFT" x="3" y="-3"/>
<Anchor point="BOTTOMRIGHT" x="-3" y="3"/>
</Anchors>
</Texture>
</Layer>
</Layers>
</Frame>
</Frames>
<Layers>
<Layer level="OVERLAY">
<FontString parentKey="Text" inherits="GameFontWhite" wordwrap="false" justifyH="RIGHT">
<Anchors>
<Anchor point="LEFT" x="2"/>
<Anchor point="RIGHT" relativeKey="$parent.Arrow" relativePoint="LEFT" x="-4"/>
</Anchors>
</FontString>
</Layer>
</Layers>
<Scripts>
<OnLoad method="OnLoad"/>
<OnShow method="OnShow"/>
<OnEnter method="OnEnter"/>
<OnLeave method="OnLeave"/>
</Scripts>
</DropdownButton>
</Ui>
+14 -22
View File
@@ -110,6 +110,12 @@ pfUI:RegisterModule("addons", function ()
return selected_addons
end
local selectedProfile
local function IsSelectedProfile(profile)
return profile == selectedProfile
end
local function SetAddonProfile(profile)
-- create new profile if not existing
if not pfUI_addon_profiles[profile] then
@@ -117,7 +123,8 @@ pfUI:RegisterModule("addons", function ()
end
-- set dropdown to profile
pfUI.addons.profile.dropdown:SetSelectionByText(profile)
selectedProfile = profile
pfUI.addons.profile.dropdown:GenerateMenu()
-- load profile
local selected = {}
@@ -163,7 +170,7 @@ pfUI:RegisterModule("addons", function ()
pfUI.addons.profile.del:SetText("-")
pfUI.addons.profile.del:SetTextColor(1,.5,.5,1)
pfUI.addons.profile.del:SetScript("OnClick", function() -- TODO
local id, name = pfUI.addons.profile.dropdown:GetSelection()
local name = selectedProfile
if not name then return end
CreateQuestionDialog(T["Delete profile"] .. " '|cff33ffcc" .. name .. "|r'?", function()
pfUI_addon_profiles[name] = nil
@@ -193,26 +200,13 @@ pfUI:RegisterModule("addons", function ()
end)
-- addon profile: dropdown
pfUI.addons.profile.dropdown = CreateDropDownButton("pfAddonListProfileList", pfUI.addons.profile)
pfUI.addons.profile.dropdown:SetBackdrop(nil)
pfUI.addons.profile.dropdown:ClearAllPoints()
pfUI.addons.profile.dropdown = CreateFrame("DropdownButton", nil, pfUI.addons.profile, "pfUIDropdownTemplate")
pfUI.addons.profile.dropdown:SetPoint("RIGHT", pfUI.addons.profile.add, "LEFT", -2, 0)
pfUI.addons.profile.dropdown:SetWidth(220)
pfUI.addons.profile.dropdown:SetMenu(function()
local menu = {}
for name, list in pairs(pfUI_addon_profiles) do
local name = name
local entry = {}
entry.text = name
entry.checked = false
entry.func = function()
SetAddonProfile(name)
end
table.insert(menu, entry)
pfUI.addons.profile.dropdown:SetupMenu(function(dropdown, rootDescription)
for name in pairs(pfUI_addon_profiles) do
rootDescription:CreateRadio(name, IsSelectedProfile, SetAddonProfile, name)
end
return menu
end)
local function AddDependencyLines(header, deps)
@@ -263,9 +257,7 @@ pfUI:RegisterModule("addons", function ()
local function InputOnClick(self)
SetAddonEnabled(self:GetParent().addon.index, self:GetChecked())
local _, name = pfUI.addons.profile.dropdown:GetSelection()
name = name or T["Current"]
pfUI_addon_profiles[name] = GetSelectedAddonsList()
pfUI_addon_profiles[selectedProfile or T["Current"]] = GetSelectedAddonsList()
end
local function InitRow(row, addon)
+63 -125
View File
@@ -204,66 +204,37 @@ pfUI:RegisterModule("equipmentmanager", function()
end)
-- ============================================================
-- Per-row context menu (single instance, repositioned per click).
-- Triggered by the gear icon on each set row.
-- Per-row context menu, opened from the gear icon on each set row.
-- ============================================================
local rowMenu = CreateFrame("Frame", "pfEqMgrRowMenu", UIParent)
rowMenu:SetFrameStrata("DIALOG")
rowMenu:SetSize(140, 50);
rowMenu:Hide()
CreateBackdrop(rowMenu, nil, nil, .95)
CreateBackdropShadow(rowMenu)
rowMenu:EnableMouse(true)
-- Close on click outside via GLOBAL_MOUSE_DOWN (fires on any click
-- without consuming it). The anchorBtn check defers the gear-click
-- toggle to the gear's own OnClick so opening doesn't trigger close.
rowMenu:RegisterEvent("GLOBAL_MOUSE_DOWN")
rowMenu:SetScript("OnEvent", function()
if not this:IsShown() then return end
if MouseIsOverHitRect(this) then return end
if this.anchorBtn and MouseIsOverHitRect(this.anchorBtn) then return end
this:Hide()
end)
tinsert(UISpecialFrames, "pfEqMgrRowMenu") -- Escape closes it
rowMenu.changeBtn = CreateFrame("Button", nil, rowMenu, "UIPanelButtonTemplate")
rowMenu.changeBtn:SetSize(130, 20);
rowMenu.changeBtn:SetPoint("TOPLEFT", rowMenu, "TOPLEFT", 5, -3)
rowMenu.changeBtn:SetText(EQUIPMENT_SET_EDIT)
SkinButton(rowMenu.changeBtn)
rowMenu.changeBtn:SetScript("OnClick", function()
rowMenu:Hide()
if not rowMenu.targetSetID then return end
local name, icon = C_EquipmentSet.GetEquipmentSetInfo(rowMenu.targetSetID)
selectedSetID = rowMenu.targetSetID
local function EditSet(setID)
local name, icon = C_EquipmentSet.GetEquipmentSetInfo(setID)
selectedSetID = setID
OpenNamePopup("save", name, icon)
end)
end
rowMenu.deleteBtn = CreateFrame("Button", nil, rowMenu, "UIPanelButtonTemplate")
rowMenu.deleteBtn:SetSize(130, 20);
rowMenu.deleteBtn:SetPoint("TOP", rowMenu.changeBtn, "BOTTOM", 0, -2)
rowMenu.deleteBtn:SetText(DELETE)
SkinButton(rowMenu.deleteBtn)
rowMenu.deleteBtn:SetScript("OnClick", function()
rowMenu:Hide()
if not rowMenu.targetSetID then return end
local targetID = rowMenu.targetSetID
local name = C_EquipmentSet.GetEquipmentSetInfo(targetID)
local function DeleteSet(setID)
local name = C_EquipmentSet.GetEquipmentSetInfo(setID)
StaticPopupDialogs["PFUI_EQMGR_DELETE"] = {
text = string.format(CONFIRM_DELETE_EQUIPMENT_SET, name or "?"),
button1 = YES, button2 = NO,
OnAccept = function()
pendingIgnoredToggles[targetID] = nil
C_EquipmentSet.DeleteEquipmentSet(targetID)
if selectedSetID == targetID then selectedSetID = nil end
pendingIgnoredToggles[setID] = nil
C_EquipmentSet.DeleteEquipmentSet(setID)
if selectedSetID == setID then selectedSetID = nil end
pfUI.equipmentmanager.Refresh()
end,
timeout = 0, whileDead = 1, hideOnEscape = 1, exclusive = 1,
}
StaticPopup_Show("PFUI_EQMGR_DELETE")
end)
end
-- The row owns the menu, not the gear: the gear hides when the cursor
-- leaves the row for the menu, and a menu closes with its owner.
local function GenerateSetMenu(row, rootDescription)
rootDescription:CreateButton(EQUIPMENT_SET_EDIT, EditSet, row.setID)
rootDescription:CreateButton(DELETE, DeleteSet, row.setID)
end
-- ============================================================
-- Set list (left column)
@@ -303,20 +274,9 @@ pfUI:RegisterModule("equipmentmanager", function()
-- moving onto the gear does not leave the row
row.gear:SetPropagateMouseMotion(true)
row.gear:Hide()
row.menuMixin = pfUIMenuStyleMixin
row.gear:SetScript("OnClick", function()
if not row.setID then return end
-- Toggle: clicking the gear that owns the open menu closes it.
-- GLOBAL_MOUSE_DOWN's anchorBtn check excludes the gear, so the
-- close has to happen here.
if rowMenu:IsShown() and rowMenu.targetSetID == row.setID then
rowMenu:Hide()
return
end
rowMenu.targetSetID = row.setID
rowMenu.anchorBtn = row.gear
rowMenu:ClearAllPoints()
rowMenu:SetPoint("TOPRIGHT", row.gear, "BOTTOMRIGHT", 0, 0)
rowMenu:Show()
if row.setID then MenuUtil.CreateContextMenu(row, GenerateSetMenu) end
end)
row:SetScript("OnClick", function()
@@ -904,19 +864,6 @@ pfUI:RegisterModule("equipmentmanager", function()
return b
end
-- Dropdown entries carry a `.value`; select one by value instead of index.
local function SelectDropdownValue(dd, value)
local menu = dd:GetMenu()
for i, entry in ipairs(menu or {}) do
if entry.value == value then
dd:SetSelection(i)
return
end
end
dd.id = nil
dd.text:SetText("")
end
local function Print(msg)
DEFAULT_CHAT_FRAME:AddMessage("|cff33ffccpf|cffffffffUI|r: " .. msg)
end
@@ -1783,9 +1730,10 @@ pfUI:RegisterModule("equipmentmanager", function()
end
local function EditorDropdown(row)
local dd = CreateDropDownButton(nil, editor)
local dd = CreateFrame("DropdownButton", nil, editor, "pfUIDropdownTemplate")
dd:SetWidth(190)
dd:SetPoint("TOPRIGHT", editor, "TOPRIGHT", 0, EDITOR_ROW_Y[row])
CreateBackdrop(dd, nil, true)
return dd
end
@@ -1801,41 +1749,49 @@ pfUI:RegisterModule("equipmentmanager", function()
RefreshTriggerPanel()
end
-- The radio callbacks for one field of the selected trigger; a trigger
-- without the field reads as `default`.
local function TriggerField(field, default)
local function IsSelected(value)
local t = SelectedTrigger()
return t ~= nil and (t[field] or default) == value
end
local function SetSelected(value)
local t = SelectedTrigger()
if not t then return end
t[field] = value
OnTriggerEdited()
end
return IsSelected, SetSelected
end
EditorLabel(T["When"], 1)
local ddType = EditorDropdown(1)
ddType:SetMenu(function()
local menu = {}
local IsType = TriggerField("type")
local function SetType(key)
local t = SelectedTrigger()
if not t or t.type == key then return end
t.type = key
t.value = DefaultTriggerValue(key)
OnTriggerEdited()
end
ddType:SetupMenu(function(dropdown, rootDescription)
for _, info in ipairs(TRIGGER_TYPES) do
if info.value ~= "list" or info.options then
local key = info.key
table.insert(menu, { text = info.text, value = key, func = function()
local t = SelectedTrigger()
if not t or t.type == key then return end
t.type = key
t.value = DefaultTriggerValue(key)
OnTriggerEdited()
end })
rootDescription:CreateRadio(info.text, IsType, SetType, info.key)
end
end
return menu
end)
local valueLabel = EditorLabel(T["Value"], 2)
local ddValue = EditorDropdown(2)
ddValue:SetMenu(function()
local menu = {}
local IsValue, SetValue = TriggerField("value")
ddValue:SetupMenu(function(dropdown, rootDescription)
local t = SelectedTrigger()
local info = t and TRIGGER_TYPE[t.type]
for _, o in ipairs(info and info.options or {}) do
local value = o.value
table.insert(menu, { text = o.text, value = value, func = function()
local t = SelectedTrigger()
if not t then return end
t.value = value
OnTriggerEdited()
end })
rootDescription:CreateRadio(o.text, IsValue, SetValue, o.value)
end
return menu
end)
local editValue = CreateTextBox(nil, editor)
@@ -1907,39 +1863,22 @@ pfUI:RegisterModule("equipmentmanager", function()
EditorLabel(T["Equip"], 3)
local ddSet = EditorDropdown(3)
ddSet:SetMenu(function()
local menu = {}
local IsSet, SetSet = TriggerField("setID")
ddSet:SetupMenu(function(dropdown, rootDescription)
for _, id in ipairs(GetVisibleSetIDs()) do
local setID = id
table.insert(menu, { text = SetName(setID), value = setID, func = function()
local t = SelectedTrigger()
if not t then return end
t.setID = setID
OnTriggerEdited()
end })
rootDescription:CreateRadio(SetName(id), IsSet, SetSet, id)
end
return menu
end)
EditorLabel(T["When It Ends"], 4)
local ddLeave = EditorDropdown(4)
ddLeave:SetMenu(function()
local function Choose(value)
return function()
local t = SelectedTrigger()
if not t then return end
t.leave = value
OnTriggerEdited()
end
end
local menu = {
{ text = T["Restore Previous Gear"], value = "restore", func = Choose("restore") },
{ text = T["Do Nothing"], value = "none", func = Choose("none") },
}
local IsLeave, SetLeave = TriggerField("leave", "restore")
ddLeave:SetupMenu(function(dropdown, rootDescription)
rootDescription:CreateRadio(T["Restore Previous Gear"], IsLeave, SetLeave, "restore")
rootDescription:CreateRadio(T["Do Nothing"], IsLeave, SetLeave, "none")
for _, id in ipairs(GetVisibleSetIDs()) do
table.insert(menu, { text = T["Equip"] .. " " .. SetName(id), value = id, func = Choose(id) })
rootDescription:CreateRadio(T["Equip"] .. " " .. SetName(id), IsLeave, SetLeave, id)
end
return menu
end)
editor.noSets = editor:CreateFontString(nil, "OVERLAY", "GameFontDisableSmall")
@@ -1984,7 +1923,7 @@ pfUI:RegisterModule("equipmentmanager", function()
editor:Show()
editor.placeholder:Hide()
SelectDropdownValue(ddType, t.type)
ddType:GenerateMenu()
local info = TRIGGER_TYPE[t.type]
local kind = info and info.value
@@ -1993,7 +1932,7 @@ pfUI:RegisterModule("equipmentmanager", function()
editValue:SetShown(kind == "text")
btnCurrentZone:SetShown(t.type == "zone")
if kind == "list" then
SelectDropdownValue(ddValue, t.value)
ddValue:GenerateMenu()
elseif kind == "text" then
editValue:ClearAllPoints()
editValue:SetPoint("TOPLEFT", editor, "TOPRIGHT", -190, EDITOR_ROW_Y[2])
@@ -2014,8 +1953,8 @@ pfUI:RegisterModule("equipmentmanager", function()
local hasSets = table.getn(GetVisibleSetIDs()) > 0
ddSet:SetShown(hasSets)
editor.noSets:SetShown(not hasSets)
SelectDropdownValue(ddSet, t.setID)
SelectDropdownValue(ddLeave, t.leave or "restore")
ddSet:GenerateMenu()
ddLeave:GenerateMenu()
end
triggerPanel:SetScript("OnShow", function() RefreshTriggerPanel() end)
@@ -2027,7 +1966,6 @@ pfUI:RegisterModule("equipmentmanager", function()
RefreshTriggerRows()
end)
triggerPanel:SetScript("OnHide", function()
for _, dd in ipairs({ ddType, ddValue, ddSet, ddLeave }) do dd:HideMenu() end
editValue:ClearFocus()
end)
+42 -46
View File
@@ -48,9 +48,8 @@ pfUI:RegisterModule("gui", function ()
end})
function EntryUpdate()
-- detect and skip during dropdowns
local focus = GetMouseFocus()
if focus and focus.parent and focus.parent.menu then
-- skip while the cursor is over an open menu
if Menu.GetManager():ContainsCursor() then
if this.over then
this.tex:Hide()
this.over = nil
@@ -344,45 +343,43 @@ pfUI:RegisterModule("gui", function ()
-- use dropdown widget
if widget == "dropdown" and values then
frame.input = CreateDropDownButton(nil, frame)
frame.input:SetBackdrop(nil)
frame.input.menuframe:SetParent(pfUI.gui)
local function IsSelected(value)
return category[config] == value
end
local function SetSelected(value)
if category[config] ~= value then
category[config] = value
if ufunc then ufunc() else pfUI.gui.settingChanged = true end
pfUI.events:TriggerEvent("config:changed", category, config)
end
end
frame.input = CreateFrame("DropdownButton", nil, frame, "pfUIDropdownTemplate")
frame.input:SetPoint("RIGHT", frame, "RIGHT", 0, 0)
frame.input:SetWidth(180)
frame.input:SetMenu(function()
local menu = {}
for i, k in pairs(_G.type(values) == "function" and values() or values) do
local entry = {}
frame.input:SetupMenu(function(dropdown, rootDescription)
for _, k in pairs(_G.type(values) == "function" and values() or values) do
-- get human readable
local value, text = strsplit(":", k)
text = text or value
entry.text = text
entry.func = function()
if category and category[config] ~= value then
category[config] = value
if ufunc then ufunc() else pfUI.gui.settingChanged = true end
pfUI.events:TriggerEvent("config:changed", category, config)
end
end
if category and category[config] == value then
frame.input.current = i
end
table.insert(menu, entry)
rootDescription:CreateRadio(text or value, IsSelected, SetSelected, value)
end
return menu
end)
frame.input:SetSelection(frame.input.current)
end
-- use list widget
if widget == "list" then
-- index of the selected entry among the "#" separated ones
local selected
local function IsSelected(index)
return index == selected
end
local function Select(index)
selected = index
end
frame.del = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
SkinButton(frame.del)
frame.del:SetWidth(16)
@@ -392,15 +389,16 @@ pfUI:RegisterModule("gui", function ()
frame.del:SetText("-")
frame.del:SetTextColor(1,.5,.5,1)
frame.del:SetScript("OnClick", function()
local sel = frame.input:GetSelection()
if not selected then return end
local newconf = ""
for id, val in pairs({strsplit("#", category[config])}) do
if id ~= sel then newconf = newconf .. "#" .. val end
for id, val in ipairs({strsplit("#", category[config])}) do
if id ~= selected and val ~= "" then newconf = newconf .. "#" .. val end
end
selected = nil
category[config] = newconf
if ufunc then ufunc() else pfUI.gui.settingChanged = true end
pfUI.events:TriggerEvent("config:changed", category, config)
frame.input:UpdateMenu()
frame.input:GenerateMenu()
end)
frame.add = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
@@ -416,21 +414,19 @@ pfUI:RegisterModule("gui", function ()
category[config] = category[config] .. "#" .. this:GetParent().input:GetText()
if ufunc then ufunc() else pfUI.gui.settingChanged = true end
pfUI.events:TriggerEvent("config:changed", category, config)
frame.input:UpdateMenu()
frame.input:GenerateMenu()
end, false, true)
end)
frame.input = CreateDropDownButton(nil, frame)
frame.input:SetBackdrop(nil)
frame.input.menuframe:SetParent(pfUI.gui)
frame.input = CreateFrame("DropdownButton", nil, frame, "pfUIDropdownTemplate")
frame.input:SetPoint("RIGHT", frame.add, "LEFT", -2, 0)
frame.input:SetWidth(140)
frame.input:SetMenu(function()
local menu = {}
for i, val in pairs({strsplit("#", category[config])}) do
table.insert(menu, { text = val })
frame.input:SetupMenu(function(dropdown, rootDescription)
for id, val in ipairs({strsplit("#", category[config])}) do
if val ~= "" then
rootDescription:CreateRadio(val, IsSelected, Select, id)
end
end
return menu
end)
end
@@ -2700,8 +2696,8 @@ pfUI:RegisterModule("gui", function ()
elseif is_horizontal then
if uneven ~= "Left" and uneven ~= "Right" then C.bars["bar"..id].uneven = "Left" end
end
if uneven_frame and uneven_frame.input and uneven_frame.input.UpdateMenu then
uneven_frame.input:UpdateMenu()
if uneven_frame then
uneven_frame.input:GenerateMenu()
end
if U["bars"] then U["bars"]() end
end
+56
View File
@@ -35,6 +35,62 @@ pfUI:RegisterModule("skin", function ()
CreateBackdropShadow(_G["DropDownList"..i.."Backdrop"])
end
-- ClassicAPI menus that don't name a style of their own take pfUI's
function MenuVariants.GetDefaultMenuMixin() return pfUIMenuStyleMixin end
function MenuVariants.GetDefaultContextMenuMixin() return pfUIMenuStyleMixin end
-- ClassicAPI menus draw their checkboxes and radios with these. Both get a
-- pfUI box: a checked box holds a check, a selected radio a filled square.
local function CreateSelectionBox(frame, text)
local _, border = GetBorderSize()
local box = frame:AttachTexture()
frame.leftTexture1 = box
box:SetDrawLayer("BORDER")
box:SetPoint("LEFT")
box:SetSize(12, 12)
box:SetColorTexture(GetStringColorObject(C.appearance.border.color):GetRGBA())
local inside = frame:AttachTexture()
inside:SetDrawLayer("ARTWORK")
inside:SetPoint("TOPLEFT", box, "TOPLEFT", border, -border)
inside:SetPoint("BOTTOMRIGHT", box, "BOTTOMRIGHT", -border, border)
local r, g, b = GetStringColorObject(C.appearance.border.background):GetRGB()
inside:SetColorTexture(r, g, b, 1)
local fontString = frame:AttachFontString()
frame.fontString = fontString
fontString:SetPoint("LEFT", box, "RIGHT", 6, 0)
fontString:SetHeight(20)
fontString:SetTextToFit(text)
return box
end
function MenuVariants.CreateCheckbox(text, frame, isSelected, data)
local box = CreateSelectionBox(frame, text)
if isSelected(data) then
local check = frame:AttachTexture()
check:SetDrawLayer("OVERLAY")
check:SetPoint("CENTER", box)
check:SetSize(16, 16)
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
end
return box
end
function MenuVariants.CreateRadio(text, frame, isSelected, data)
local box = CreateSelectionBox(frame, text)
if isSelected(data) then
local dot = frame:AttachTexture()
dot:SetDrawLayer("OVERLAY")
dot:SetPoint("TOPLEFT", box, "TOPLEFT", 3, -3)
dot:SetPoint("BOTTOMRIGHT", box, "BOTTOMRIGHT", -3, 3)
dot:SetColorTexture(.2, 1, .8, 1)
end
return box
end
if C.global.errors_limit == "1" then
UIErrorsFrame:SetHeight(25)
end
+18 -25
View File
@@ -42,7 +42,23 @@ pfUI:RegisterModule("tracking", function ()
fade:SetDuration(.5)
fade:SetSmoothing("IN_OUT")
pfUI.tracking.menu = CreateFrame("Frame", "pfUIDropDownMenuTracking", nil, "UIDropDownMenuTemplate")
pfUI.tracking.menuMixin = pfUIMenuStyleMixin
local function IsTracking(spell)
return spell.texture == state.texture
end
local function Track(spell)
SetTracking(spell.index)
end
local function GenerateTrackingMenu(owner, rootDescription)
rootDescription:CreateTitle(T["Minimap Tracking"])
for _, spell in pairs(state.spells) do
local icon = CreateTextureMarkup(spell.texture, 64, 64, 16, 16, .1, .9, .1, .9)
rootDescription:CreateRadio(icon .. " " .. spell.name, IsTracking, Track, spell)
end
end
pfUI.tracking:RegisterEvent("PLAYER_ENTERING_WORLD")
pfUI.tracking:RegisterEvent("PLAYER_AURAS_CHANGED")
@@ -59,8 +75,7 @@ pfUI:RegisterModule("tracking", function ()
pfUI.tracking:RegisterForClicks("LeftButtonUp", "RightButtonUp")
pfUI.tracking:SetScript("OnClick", function()
if arg1 == "RightButton" then
pfUI.tracking:InitMenu()
ToggleDropDownMenu(1, nil, pfUI.tracking.menu, this, -5, -5)
MenuUtil.CreateContextMenu(this, GenerateTrackingMenu)
end
if arg1 == "LeftButton" and state.texture then
CancelTrackingBuff()
@@ -128,26 +143,4 @@ pfUI:RegisterModule("tracking", function ()
function pfUI.tracking:PlayerIsDruidInCatForm(playerClass)
return playerClass == "DRUID" and GetShapeshiftFormID() == 1
end
function pfUI.tracking:InitMenu()
UIDropDownMenu_Initialize(pfUI.tracking.menu, function ()
UIDropDownMenu_AddButton({text = T["Minimap Tracking"], isTitle = 1})
for _, spell in pairs(state.spells) do
UIDropDownMenu_AddButton({
text = spell.name,
icon = spell.texture,
tCoordLeft = .1,
tCoordRight = .9,
tCoordTop = .1,
tCoordBottom = .9,
checked = spell.texture == state.texture,
arg1 = spell,
func = function (arg1)
SetTracking(arg1.index)
CloseDropDownMenus()
end
})
end
end, "MENU")
end
end)