diff --git a/api/ui-widgets.lua b/api/ui-widgets.lua
index ad2b7a18..afda557c 100644
--- a/api/ui-widgets.lua
+++ b/api/ui-widgets.lua
@@ -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()
diff --git a/api/ui-widgets.xml b/api/ui-widgets.xml
index 9fd6dc72..df083d14 100644
--- a/api/ui-widgets.xml
+++ b/api/ui-widgets.xml
@@ -102,4 +102,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/addons.lua b/modules/addons.lua
index aac03cc8..37f16cc5 100644
--- a/modules/addons.lua
+++ b/modules/addons.lua
@@ -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)
diff --git a/modules/equipmentmanager.lua b/modules/equipmentmanager.lua
index b32e8ad0..2bd6aa83 100644
--- a/modules/equipmentmanager.lua
+++ b/modules/equipmentmanager.lua
@@ -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)
diff --git a/modules/gui.lua b/modules/gui.lua
index dc59de0a..beb96f44 100644
--- a/modules/gui.lua
+++ b/modules/gui.lua
@@ -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
diff --git a/modules/skin.lua b/modules/skin.lua
index d7f98e49..69081ee8 100644
--- a/modules/skin.lua
+++ b/modules/skin.lua
@@ -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
diff --git a/modules/tracking.lua b/modules/tracking.lua
index 5e4e99a9..974edc97 100644
--- a/modules/tracking.lua
+++ b/modules/tracking.lua
@@ -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)
\ No newline at end of file