Add search to the icon pickers and fix set editing

Equipment manager:
- Move the OK button next to Cancel at the bottom-right.
- Add an icon search box in the freed bottom-left space.
- Shift the popup contents up and shrink the window after the title
  was removed.
- Show the current icon when you edit a set. Keep a full icon path as
  is instead of adding a second prefix, and match grid icons by name.
- Close the name/icon popup when the manager frame closes. Remove the
  duplicate OnHide hook.

Both pickers now use Blizzard global strings for the labels and the
icon filters.
This commit is contained in:
Brues
2026-08-05 21:43:51 -05:00
parent 0cc9cf4165
commit 0778f9a7be
2 changed files with 124 additions and 86 deletions
+115 -82
View File
@@ -1,11 +1,10 @@
-- Equipment Manager module -- Equipment Manager module
-- Backport of the 4.3.4 GearManagerDialog UI on top of ClassicAPI's -- Backport of the 4.3.4 GearManagerDialog UI on top of ClassicAPI's C_EquipmentSet.* API.
-- C_EquipmentSet.* API. Adds a 6th tab to CharacterFrame.
pfUI:RegisterModule("equipmentmanager", function() pfUI:RegisterModule("equipmentmanager", function()
if not C_EquipmentSet or not C_EquipmentSet.CanUseEquipmentSets() then return end if not C_EquipmentSet or not C_EquipmentSet.CanUseEquipmentSets() then return end
pfUI.equipmentmanager = pfUI.equipmentmanager or {} pfUI.equipmentmanager = {}
local SET_ROW_HEIGHT = 36 local SET_ROW_HEIGHT = 36
@@ -55,7 +54,7 @@ pfUI:RegisterModule("equipmentmanager", function()
local function EquipSet(setID) local function EquipSet(setID)
if not setID then return end if not setID then return end
if C_EquipmentSet.EquipmentSetContainsLockedItems(setID) then if C_EquipmentSet.EquipmentSetContainsLockedItems(setID) then
UIErrorsFrame:AddMessage(ERR_CLIENT_LOCKED_OUT or "Locked items in set", 1, .1, .1, 1) UIErrorsFrame:AddMessage(ERR_CLIENT_LOCKED_OUT, 1, .1, .1, 1)
return return
end end
ClearCursor() ClearCursor()
@@ -68,8 +67,7 @@ pfUI:RegisterModule("equipmentmanager", function()
-- ============================================================ -- ============================================================
local frame = CreateFrame("Frame", "pfEquipmentManagerFrame", CharacterFrame) local frame = CreateFrame("Frame", "pfEquipmentManagerFrame", CharacterFrame)
frame:SetWidth(220) frame:SetSize(220, 350)
frame:SetHeight(350)
frame:SetFrameStrata("HIGH") frame:SetFrameStrata("HIGH")
frame:SetScript("OnShow", function() frame:SetScript("OnShow", function()
this:ClearAllPoints() this:ClearAllPoints()
@@ -86,7 +84,7 @@ pfUI:RegisterModule("equipmentmanager", function()
frame.title = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal") frame.title = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
frame.title:SetPoint("TOP", frame, "TOP", 0, -10) frame.title:SetPoint("TOP", frame, "TOP", 0, -10)
frame.title:SetText(T["Equipment Manager"] or "Equipment Manager") frame.title:SetText(EQUIPMENT_MANAGER)
local closeBtn = CreateFrame("Button", nil, frame, "UIPanelCloseButton") local closeBtn = CreateFrame("Button", nil, frame, "UIPanelCloseButton")
closeBtn:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -4, -4) closeBtn:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -4, -4)
@@ -98,15 +96,14 @@ pfUI:RegisterModule("equipmentmanager", function()
-- ============================================================ -- ============================================================
local toggleBtn = CreateFrame("Button", "pfEqMgrToggleButton", PaperDollFrame) local toggleBtn = CreateFrame("Button", "pfEqMgrToggleButton", PaperDollFrame)
toggleBtn:SetWidth(28) toggleBtn:SetSize(28, 28)
toggleBtn:SetHeight(28)
toggleBtn:SetPoint("BOTTOM", CharacterHandsSlot, "TOP", 0, 4) toggleBtn:SetPoint("BOTTOM", CharacterHandsSlot, "TOP", 0, 4)
toggleBtn:SetNormalTexture(pfUI.path.."\\img\\UI-GearManager-Button") toggleBtn:SetNormalTexture(pfUI.path.."\\img\\UI-GearManager-Button")
toggleBtn:SetPushedTexture(pfUI.path.."\\img\\UI-GearManager-Button-Pushed") toggleBtn:SetPushedTexture(pfUI.path.."\\img\\UI-GearManager-Button-Pushed")
toggleBtn:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square", "ADD") toggleBtn:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square", "ADD")
toggleBtn:SetScript("OnEnter", function() toggleBtn:SetScript("OnEnter", function()
GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetText(T["Equipment Manager"] or "Equipment Manager") GameTooltip:SetText(PAPERDOLL_EQUIPMENTMANAGER)
GameTooltip:Show() GameTooltip:Show()
end) end)
toggleBtn:SetScript("OnLeave", function() GameTooltip:Hide() end) toggleBtn:SetScript("OnLeave", function() GameTooltip:Hide() end)
@@ -126,13 +123,13 @@ pfUI:RegisterModule("equipmentmanager", function()
-- ============================================================ -- ============================================================
local btnEquip = CreateFrame("Button", "pfEqMgrEquip", frame, "UIPanelButtonTemplate") local btnEquip = CreateFrame("Button", "pfEqMgrEquip", frame, "UIPanelButtonTemplate")
btnEquip:SetWidth(86); btnEquip:SetHeight(22); btnEquip:SetText(T["Equip"] or "Equip") btnEquip:SetSize(86, 22); btnEquip:SetText(EQUIPSET_EQUIP)
btnEquip:SetPoint("TOPLEFT", frame, "TOPLEFT", 16, -30) btnEquip:SetPoint("TOPLEFT", frame, "TOPLEFT", 16, -30)
SkinButton(btnEquip) SkinButton(btnEquip)
btnEquip:SetScript("OnClick", function() EquipSet(selectedSetID) end) btnEquip:SetScript("OnClick", function() EquipSet(selectedSetID) end)
local btnSave = CreateFrame("Button", "pfEqMgrSave", frame, "UIPanelButtonTemplate") local btnSave = CreateFrame("Button", "pfEqMgrSave", frame, "UIPanelButtonTemplate")
btnSave:SetWidth(86); btnSave:SetHeight(22); btnSave:SetText(T["Save"] or "Save") btnSave:SetSize(86, 22); btnSave:SetText(SAVE)
btnSave:SetPoint("LEFT", btnEquip, "RIGHT", 6, 0) btnSave:SetPoint("LEFT", btnEquip, "RIGHT", 6, 0)
SkinButton(btnSave) SkinButton(btnSave)
btnSave:SetScript("OnClick", function() btnSave:SetScript("OnClick", function()
@@ -141,7 +138,7 @@ pfUI:RegisterModule("equipmentmanager", function()
if not name then return end if not name then return end
local targetID = selectedSetID local targetID = selectedSetID
StaticPopupDialogs["PFUI_EQMGR_SAVE_CONFIRM"] = { StaticPopupDialogs["PFUI_EQMGR_SAVE_CONFIRM"] = {
text = string.format(T["Would you like to save the equipment set '%s'?"] or "Would you like to save the equipment set '%s'?", name), text = string.format(CONFIRM_SAVE_EQUIPMENT_SET, name),
button1 = YES, button2 = NO, button1 = YES, button2 = NO,
OnAccept = function() OnAccept = function()
C_EquipmentSet.ClearIgnoredSlotsForSave() C_EquipmentSet.ClearIgnoredSlotsForSave()
@@ -166,7 +163,7 @@ pfUI:RegisterModule("equipmentmanager", function()
local rowMenu = CreateFrame("Frame", "pfEqMgrRowMenu", UIParent) local rowMenu = CreateFrame("Frame", "pfEqMgrRowMenu", UIParent)
rowMenu:SetFrameStrata("DIALOG") rowMenu:SetFrameStrata("DIALOG")
rowMenu:SetWidth(140); rowMenu:SetHeight(50) rowMenu:SetSize(140, 50);
rowMenu:Hide() rowMenu:Hide()
CreateBackdrop(rowMenu, nil, nil, .95) CreateBackdrop(rowMenu, nil, nil, .95)
CreateBackdropShadow(rowMenu) CreateBackdropShadow(rowMenu)
@@ -185,9 +182,9 @@ pfUI:RegisterModule("equipmentmanager", function()
tinsert(UISpecialFrames, "pfEqMgrRowMenu") -- Escape closes it tinsert(UISpecialFrames, "pfEqMgrRowMenu") -- Escape closes it
rowMenu.changeBtn = CreateFrame("Button", nil, rowMenu, "UIPanelButtonTemplate") rowMenu.changeBtn = CreateFrame("Button", nil, rowMenu, "UIPanelButtonTemplate")
rowMenu.changeBtn:SetWidth(130); rowMenu.changeBtn:SetHeight(20) rowMenu.changeBtn:SetSize(130, 20);
rowMenu.changeBtn:SetPoint("TOPLEFT", rowMenu, "TOPLEFT", 5, -3) rowMenu.changeBtn:SetPoint("TOPLEFT", rowMenu, "TOPLEFT", 5, -3)
rowMenu.changeBtn:SetText(T["Change Name/Icon"] or "Change Name/Icon") rowMenu.changeBtn:SetText(EQUIPMENT_SET_EDIT)
SkinButton(rowMenu.changeBtn) SkinButton(rowMenu.changeBtn)
rowMenu.changeBtn:SetScript("OnClick", function() rowMenu.changeBtn:SetScript("OnClick", function()
rowMenu:Hide() rowMenu:Hide()
@@ -198,9 +195,9 @@ pfUI:RegisterModule("equipmentmanager", function()
end) end)
rowMenu.deleteBtn = CreateFrame("Button", nil, rowMenu, "UIPanelButtonTemplate") rowMenu.deleteBtn = CreateFrame("Button", nil, rowMenu, "UIPanelButtonTemplate")
rowMenu.deleteBtn:SetWidth(130); rowMenu.deleteBtn:SetHeight(20) rowMenu.deleteBtn:SetSize(130, 20);
rowMenu.deleteBtn:SetPoint("TOP", rowMenu.changeBtn, "BOTTOM", 0, -2) rowMenu.deleteBtn:SetPoint("TOP", rowMenu.changeBtn, "BOTTOM", 0, -2)
rowMenu.deleteBtn:SetText(T["Delete"] or "Delete") rowMenu.deleteBtn:SetText(DELETE)
SkinButton(rowMenu.deleteBtn) SkinButton(rowMenu.deleteBtn)
rowMenu.deleteBtn:SetScript("OnClick", function() rowMenu.deleteBtn:SetScript("OnClick", function()
rowMenu:Hide() rowMenu:Hide()
@@ -208,7 +205,7 @@ pfUI:RegisterModule("equipmentmanager", function()
local targetID = rowMenu.targetSetID local targetID = rowMenu.targetSetID
local name = C_EquipmentSet.GetEquipmentSetInfo(targetID) local name = C_EquipmentSet.GetEquipmentSetInfo(targetID)
StaticPopupDialogs["PFUI_EQMGR_DELETE"] = { StaticPopupDialogs["PFUI_EQMGR_DELETE"] = {
text = string.format(T["Delete equipment set '%s'?"] or "Delete equipment set '%s'?", name or "?"), text = string.format(CONFIRM_DELETE_EQUIPMENT_SET, name or "?"),
button1 = YES, button2 = NO, button1 = YES, button2 = NO,
OnAccept = function() OnAccept = function()
pendingIgnoredToggles[targetID] = nil pendingIgnoredToggles[targetID] = nil
@@ -229,9 +226,8 @@ pfUI:RegisterModule("equipmentmanager", function()
local LIST_ROW_STRIDE = SET_ROW_HEIGHT + 2 local LIST_ROW_STRIDE = SET_ROW_HEIGHT + 2
local listFrame = CreateFrame("Frame", nil, frame) local listFrame = CreateFrame("Frame", nil, frame)
listFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 16, -58) listFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 16, -58)
listFrame:SetWidth(180)
-- Height fits N rows + (N-1) inter-row gaps + 3px top/bottom padding. -- Height fits N rows + (N-1) inter-row gaps + 3px top/bottom padding.
listFrame:SetHeight(LIST_VISIBLE_ROWS * LIST_ROW_STRIDE + 4) listFrame:SetSize(180, LIST_VISIBLE_ROWS * LIST_ROW_STRIDE + 4)
CreateBackdrop(listFrame, nil, nil, .75) CreateBackdrop(listFrame, nil, nil, .75)
-- Mouse-wheel scroll: list of [sets..., newSetRow] is virtualized -- Mouse-wheel scroll: list of [sets..., newSetRow] is virtualized
@@ -247,15 +243,13 @@ pfUI:RegisterModule("equipmentmanager", function()
local setRows = {} local setRows = {}
local function CreateSetRow() local function CreateSetRow()
local row = CreateFrame("Button", nil, listFrame) local row = CreateFrame("Button", nil, listFrame)
row:SetWidth(170) row:SetSize(170, SET_ROW_HEIGHT)
row:SetHeight(SET_ROW_HEIGHT)
-- Position is set per-Refresh based on the row's visible slot; -- Position is set per-Refresh based on the row's visible slot;
-- start anchored to avoid uninitialized geometry before first Refresh. -- start anchored to avoid uninitialized geometry before first Refresh.
row:SetPoint("TOPLEFT", listFrame, "TOPLEFT", 5, -3) row:SetPoint("TOPLEFT", listFrame, "TOPLEFT", 5, -3)
row.icon = row:CreateTexture(nil, "ARTWORK") row.icon = row:CreateTexture(nil, "ARTWORK")
row.icon:SetWidth(30) row.icon:SetSize(30, 30)
row.icon:SetHeight(30)
row.icon:SetPoint("LEFT", row, "LEFT", 2, 0) row.icon:SetPoint("LEFT", row, "LEFT", 2, 0)
row.icon:SetTexCoord(.08, .92, .08, .92) row.icon:SetTexCoord(.08, .92, .08, .92)
@@ -270,7 +264,7 @@ pfUI:RegisterModule("equipmentmanager", function()
row.highlight:Hide() row.highlight:Hide()
row.gear = CreateFrame("Button", nil, row) row.gear = CreateFrame("Button", nil, row)
row.gear:SetWidth(16); row.gear:SetHeight(16) row.gear:SetSize(16, 16);
row.gear:SetPoint("RIGHT", row, "RIGHT", -4, 0) row.gear:SetPoint("RIGHT", row, "RIGHT", -4, 0)
row.gear.tex = row.gear:CreateTexture(nil, "ARTWORK") row.gear.tex = row.gear:CreateTexture(nil, "ARTWORK")
row.gear.tex:SetAllPoints(row.gear) row.gear.tex:SetAllPoints(row.gear)
@@ -338,10 +332,10 @@ pfUI:RegisterModule("equipmentmanager", function()
-- specific set index (row[i] always shows ids[i]). -- specific set index (row[i] always shows ids[i]).
local newSetRow = CreateFrame("Button", nil, listFrame) local newSetRow = CreateFrame("Button", nil, listFrame)
newSetRow:SetWidth(170); newSetRow:SetHeight(SET_ROW_HEIGHT) newSetRow:SetSize(170, SET_ROW_HEIGHT);
newSetRow.icon = newSetRow:CreateTexture(nil, "ARTWORK") newSetRow.icon = newSetRow:CreateTexture(nil, "ARTWORK")
newSetRow.icon:SetWidth(24); newSetRow.icon:SetHeight(24) newSetRow.icon:SetSize(24, 24);
newSetRow.icon:SetPoint("LEFT", newSetRow, "LEFT", 5, 0) newSetRow.icon:SetPoint("LEFT", newSetRow, "LEFT", 5, 0)
newSetRow.icon:SetTexture(pfUI.path.."\\img\\Character-Plus") newSetRow.icon:SetTexture(pfUI.path.."\\img\\Character-Plus")
@@ -349,7 +343,7 @@ pfUI:RegisterModule("equipmentmanager", function()
newSetRow.text:SetPoint("LEFT", newSetRow.icon, "RIGHT", 8, 0) newSetRow.text:SetPoint("LEFT", newSetRow.icon, "RIGHT", 8, 0)
newSetRow.text:SetPoint("RIGHT", newSetRow, "RIGHT", -4, 0) newSetRow.text:SetPoint("RIGHT", newSetRow, "RIGHT", -4, 0)
newSetRow.text:SetJustifyH("LEFT") newSetRow.text:SetJustifyH("LEFT")
newSetRow.text:SetText(T["New Set"] or "New Set") newSetRow.text:SetText(PAPERDOLL_NEWEQUIPMENTSET)
newSetRow.text:SetTextColor(0.2, 1, 0.2) newSetRow.text:SetTextColor(0.2, 1, 0.2)
newSetRow.highlight = newSetRow:CreateTexture(nil, "BACKGROUND") newSetRow.highlight = newSetRow:CreateTexture(nil, "BACKGROUND")
@@ -362,8 +356,7 @@ pfUI:RegisterModule("equipmentmanager", function()
local function MakeButton(name, label, parent, anchor, ax, ay, width) local function MakeButton(name, label, parent, anchor, ax, ay, width)
local b = CreateFrame("Button", name, parent, "UIPanelButtonTemplate") local b = CreateFrame("Button", name, parent, "UIPanelButtonTemplate")
b:SetWidth(width or 70) b:SetSize(width or 70, 22)
b:SetHeight(22)
b:SetText(label) b:SetText(label)
b:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", ax, ay) b:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", ax, ay)
SkinButton(b) SkinButton(b)
@@ -376,8 +369,7 @@ pfUI:RegisterModule("equipmentmanager", function()
local namePopup = CreateFrame("Frame", "pfEqMgrNamePopup", UIParent) local namePopup = CreateFrame("Frame", "pfEqMgrNamePopup", UIParent)
namePopup:SetFrameStrata("DIALOG") namePopup:SetFrameStrata("DIALOG")
namePopup:SetWidth(472) namePopup:SetSize(472, 484)
namePopup:SetHeight(498)
namePopup:SetPoint("CENTER", UIParent, "CENTER") namePopup:SetPoint("CENTER", UIParent, "CENTER")
namePopup:Hide() namePopup:Hide()
CreateBackdrop(namePopup, nil, nil, .9) CreateBackdrop(namePopup, nil, nil, .9)
@@ -388,39 +380,33 @@ pfUI:RegisterModule("equipmentmanager", function()
namePopup:SetScript("OnDragStart", function() this:StartMoving() end) namePopup:SetScript("OnDragStart", function() this:StartMoving() end)
namePopup:SetScript("OnDragStop", function() this:StopMovingOrSizing() end) namePopup:SetScript("OnDragStop", function() this:StopMovingOrSizing() end)
namePopup.title = namePopup:CreateFontString(nil, "OVERLAY", "GameFontNormal")
namePopup.title:SetPoint("TOP", namePopup, "TOP", 0, -10)
namePopup.title:SetText(T["Save Set"] or "Save Set")
namePopup.nameLabel = namePopup:CreateFontString(nil, "OVERLAY", "GameFontNormal") namePopup.nameLabel = namePopup:CreateFontString(nil, "OVERLAY", "GameFontNormal")
namePopup.nameLabel:SetPoint("TOPLEFT", namePopup, "TOPLEFT", 14, -34) namePopup.nameLabel:SetPoint("TOPLEFT", namePopup, "TOPLEFT", 14, -20)
namePopup.nameLabel:SetText(T["Enter Set Name (Max 16 Characters):"] or "Enter Set Name (Max 16 Characters):") namePopup.nameLabel:SetText(GEARSETS_POPUP_TEXT)
namePopup.editbox = CreateFrame("EditBox", "pfEqMgrNameEdit", namePopup, "InputBoxTemplate") namePopup.editbox = CreateFrame("EditBox", "pfEqMgrNameEdit", namePopup, "InputBoxTemplate")
namePopup.editbox:SetWidth(280) namePopup.editbox:SetSize(280, 20)
namePopup.editbox:SetHeight(20) namePopup.editbox:SetPoint("TOPLEFT", namePopup, "TOPLEFT", 14, -38)
namePopup.editbox:SetPoint("TOPLEFT", namePopup, "TOPLEFT", 14, -52)
namePopup.editbox:SetAutoFocus(false) namePopup.editbox:SetAutoFocus(false)
namePopup.editbox:SetMaxLetters(16) namePopup.editbox:SetMaxLetters(16)
CreateBackdrop(namePopup.editbox) CreateBackdrop(namePopup.editbox)
namePopup.selectedLabel = namePopup:CreateFontString(nil, "OVERLAY", "GameFontNormal") namePopup.selectedLabel = namePopup:CreateFontString(nil, "OVERLAY", "GameFontNormal")
namePopup.selectedLabel:SetPoint("TOPRIGHT", namePopup, "TOPRIGHT", -14, -28) namePopup.selectedLabel:SetPoint("TOPRIGHT", namePopup, "TOPRIGHT", -14, -14)
namePopup.selectedLabel:SetText(T["Currently Selected"] or "Currently Selected") namePopup.selectedLabel:SetText(ICON_SELECTION_TITLE_CURRENT)
namePopup.selectedLabel:SetTextColor(1, 0.82, 0) namePopup.selectedLabel:SetTextColor(1, 0.82, 0)
namePopup.selectedPreview = CreateFrame("Frame", nil, namePopup) namePopup.selectedPreview = CreateFrame("Frame", nil, namePopup)
namePopup.selectedPreview:SetWidth(42) namePopup.selectedPreview:SetSize(42, 42)
namePopup.selectedPreview:SetHeight(42) namePopup.selectedPreview:SetPoint("TOPRIGHT", namePopup, "TOPRIGHT", -14, -30)
namePopup.selectedPreview:SetPoint("TOPRIGHT", namePopup, "TOPRIGHT", -14, -44)
CreateBackdrop(namePopup.selectedPreview) CreateBackdrop(namePopup.selectedPreview)
namePopup.selectedPreview.tex = namePopup.selectedPreview:CreateTexture(nil, "ARTWORK") namePopup.selectedPreview.tex = namePopup.selectedPreview:CreateTexture(nil, "ARTWORK")
namePopup.selectedPreview.tex:SetAllPoints(namePopup.selectedPreview) namePopup.selectedPreview.tex:SetAllPoints(namePopup.selectedPreview)
namePopup.selectedPreview.tex:SetTexCoord(.08, .92, .08, .92) namePopup.selectedPreview.tex:SetTexCoord(.08, .92, .08, .92)
namePopup.iconLabel = namePopup:CreateFontString(nil, "OVERLAY", "GameFontNormal") namePopup.iconLabel = namePopup:CreateFontString(nil, "OVERLAY", "GameFontNormal")
namePopup.iconLabel:SetPoint("TOPLEFT", namePopup, "TOPLEFT", 14, -100) namePopup.iconLabel:SetPoint("TOPLEFT", namePopup, "TOPLEFT", 14, -86)
namePopup.iconLabel:SetText(T["Choose an Icon:"] or "Choose an Icon:") namePopup.iconLabel:SetText(MACRO_POPUP_CHOOSE_ICON)
-- Icon picker: 10×8 grid of buttons + scroll -- Icon picker: 10×8 grid of buttons + scroll
local ICON_GRID_COLS = 10 local ICON_GRID_COLS = 10
@@ -429,7 +415,7 @@ pfUI:RegisterModule("equipmentmanager", function()
local ICON_BTN_PAD = 6 local ICON_BTN_PAD = 6
local iconScroll = CreateFrame("ScrollFrame", "pfEqMgrIconScroll", namePopup, "FauxScrollFrameTemplate") local iconScroll = CreateFrame("ScrollFrame", "pfEqMgrIconScroll", namePopup, "FauxScrollFrameTemplate")
iconScroll:SetPoint("TOPLEFT", namePopup, "TOPLEFT", 14, -130) iconScroll:SetPoint("TOPLEFT", namePopup, "TOPLEFT", 14, -116)
iconScroll:SetWidth(ICON_GRID_COLS * (ICON_BTN_SIZE + ICON_BTN_PAD) - ICON_BTN_PAD) iconScroll:SetWidth(ICON_GRID_COLS * (ICON_BTN_SIZE + ICON_BTN_PAD) - ICON_BTN_PAD)
iconScroll:SetHeight(ICON_GRID_ROWS * (ICON_BTN_SIZE + ICON_BTN_PAD) - ICON_BTN_PAD) iconScroll:SetHeight(ICON_GRID_ROWS * (ICON_BTN_SIZE + ICON_BTN_PAD) - ICON_BTN_PAD)
@@ -441,6 +427,9 @@ pfUI:RegisterModule("equipmentmanager", function()
-- you switch the filter to "Items" and it's no longer in the visible list. -- you switch the filter to "Items" and it's no longer in the visible list.
local QUESTION_MARK = "INTERFACE\\ICONS\\INV_MISC_QUESTIONMARK" local QUESTION_MARK = "INTERFACE\\ICONS\\INV_MISC_QUESTIONMARK"
local selectedIconPath = QUESTION_MARK local selectedIconPath = QUESTION_MARK
local searchText = ""
local filtered = nil -- provider indices matching the search, or nil when empty
local RebuildFilter -- forward-declared; assigned below
local function EnsureProvider() local function EnsureProvider()
if not provider then if not provider then
@@ -462,7 +451,7 @@ pfUI:RegisterModule("equipmentmanager", function()
-- Filter dropdown: "All Icons" / "Spells" / "Items" (top right of icon area). -- Filter dropdown: "All Icons" / "Spells" / "Items" (top right of icon area).
local filterDropdown = CreateFrame("Frame", "pfEqMgrIconFilter", namePopup, "UIDropDownMenuTemplate") local filterDropdown = CreateFrame("Frame", "pfEqMgrIconFilter", namePopup, "UIDropDownMenuTemplate")
filterDropdown:SetPoint("TOPRIGHT", namePopup, "TOPRIGHT", 0, -94) filterDropdown:SetPoint("TOPRIGHT", namePopup, "TOPRIGHT", 0, -80)
local currentFilter = "all" local currentFilter = "all"
local function ApplyFilter(value) local function ApplyFilter(value)
currentFilter = value currentFilter = value
@@ -474,20 +463,21 @@ pfUI:RegisterModule("equipmentmanager", function()
-- Don't reset selection — selectedIconPath persists. If the -- Don't reset selection — selectedIconPath persists. If the
-- selected icon isn't in the new filter, no grid entry will be -- selected icon isn't in the new filter, no grid entry will be
-- highlighted but Save will still write the chosen icon. -- highlighted but Save will still write the chosen icon.
RebuildFilter()
pfUI.equipmentmanager.RefreshIconGrid() pfUI.equipmentmanager.RefreshIconGrid()
end end
end end
UIDropDownMenu_Initialize(filterDropdown, function() UIDropDownMenu_Initialize(filterDropdown, function()
local info local info
info = {}; info.text = T["All Icons"] or "All Icons"; info.value = "all" info = {}; info.text = ICON_FILTER_ALL; info.value = "all"
info.func = function() ApplyFilter("all") end info.func = function() ApplyFilter("all") end
info.checked = currentFilter == "all" info.checked = currentFilter == "all"
UIDropDownMenu_AddButton(info) UIDropDownMenu_AddButton(info)
info = {}; info.text = T["Spells"] or "Spells"; info.value = "spells" info = {}; info.text = ICON_FILTER_SPELL; info.value = "spells"
info.func = function() ApplyFilter("spells") end info.func = function() ApplyFilter("spells") end
info.checked = currentFilter == "spells" info.checked = currentFilter == "spells"
UIDropDownMenu_AddButton(info) UIDropDownMenu_AddButton(info)
info = {}; info.text = T["Items"] or "Items"; info.value = "items" info = {}; info.text = ICON_FILTER_ITEM; info.value = "items"
info.func = function() ApplyFilter("items") end info.func = function() ApplyFilter("items") end
info.checked = currentFilter == "items" info.checked = currentFilter == "items"
UIDropDownMenu_AddButton(info) UIDropDownMenu_AddButton(info)
@@ -531,9 +521,32 @@ pfUI:RegisterModule("equipmentmanager", function()
end end
end end
-- Normalize a texture path to an uppercase basename for search matching.
local function IconKey(path)
if type(path) ~= "string" then return path end
return string.gsub(string.upper(path), "^.*[\\/]", "")
end
-- Rebuild the search-filtered index list (provider indices whose icon
-- basename contains the search text); nil when the search box is empty.
function RebuildFilter()
EnsureProvider()
if searchText == "" then
filtered = nil
return
end
filtered = {}
for i = 1, provider:GetNumIcons() do
local path = provider:GetIconByIndex(i)
if type(path) == "string" and string.find(IconKey(path), searchText, 1, true) then
table.insert(filtered, i)
end
end
end
function pfUI.equipmentmanager.RefreshIconGrid() function pfUI.equipmentmanager.RefreshIconGrid()
EnsureProvider() EnsureProvider()
local numIcons = provider:GetNumIcons() local numIcons = filtered and table.getn(filtered) or provider:GetNumIcons()
local numRows = math.ceil(numIcons / ICON_GRID_COLS) local numRows = math.ceil(numIcons / ICON_GRID_COLS)
FauxScrollFrame_Update(iconScroll, numRows, ICON_GRID_ROWS, ICON_BTN_SIZE + ICON_BTN_PAD) FauxScrollFrame_Update(iconScroll, numRows, ICON_GRID_ROWS, ICON_BTN_SIZE + ICON_BTN_PAD)
local offset = FauxScrollFrame_GetOffset(iconScroll) local offset = FauxScrollFrame_GetOffset(iconScroll)
@@ -542,10 +555,11 @@ pfUI:RegisterModule("equipmentmanager", function()
local btn = iconButtons[i] local btn = iconButtons[i]
if listIdx <= numIcons then if listIdx <= numIcons then
btn:Show() btn:Show()
btn.iconIndex = listIdx local providerIdx = filtered and filtered[listIdx] or listIdx
local path = provider:GetIconByIndex(listIdx) btn.iconIndex = providerIdx
local path = provider:GetIconByIndex(providerIdx)
btn.texture:SetTexture(path) btn.texture:SetTexture(path)
if path == selectedIconPath then if IconKey(path) == IconKey(selectedIconPath) then
btn.backdrop:SetBackdropBorderColor(1, 0.82, 0, 1) btn.backdrop:SetBackdropBorderColor(1, 0.82, 0, 1)
else else
btn.backdrop:SetBackdropBorderColor(pfUI.cache.er, pfUI.cache.eg, pfUI.cache.eb, pfUI.cache.ea) btn.backdrop:SetBackdropBorderColor(pfUI.cache.er, pfUI.cache.eg, pfUI.cache.eb, pfUI.cache.ea)
@@ -568,15 +582,17 @@ pfUI:RegisterModule("equipmentmanager", function()
if provider then provider:Release(); provider = nil end if provider then provider:Release(); provider = nil end
end) end)
local btnPopupOK = MakeButton("pfEqMgrPopupOK", T["OK"] or "OK", namePopup, namePopup, 14, -340, 80) local btnPopupOK = MakeButton("pfEqMgrPopupOK", OKAY, namePopup, namePopup, 14, -340, 80)
btnPopupOK:ClearAllPoints()
btnPopupOK:SetPoint("BOTTOMLEFT", namePopup, "BOTTOMLEFT", 14, 12)
local btnPopupCancel = MakeButton("pfEqMgrPopupCancel", T["Cancel"] or "Cancel", namePopup, namePopup, 0, 0, 80) local btnPopupCancel = MakeButton("pfEqMgrPopupCancel", CANCEL, namePopup, namePopup, 0, 0, 80)
btnPopupCancel:ClearAllPoints() btnPopupCancel:ClearAllPoints()
btnPopupCancel:SetPoint("BOTTOMRIGHT", namePopup, "BOTTOMRIGHT", -14, 12) btnPopupCancel:SetPoint("BOTTOMRIGHT", namePopup, "BOTTOMRIGHT", -14, 12)
btnPopupCancel:SetScript("OnClick", function() namePopup:Hide() end) btnPopupCancel:SetScript("OnClick", function() namePopup:Hide() end)
-- Okay | Cancel, both anchored to the bottom-right corner.
btnPopupOK:ClearAllPoints()
btnPopupOK:SetPoint("BOTTOMRIGHT", btnPopupCancel, "BOTTOMLEFT", -6, 0)
btnPopupOK:SetScript("OnClick", function() btnPopupOK:SetScript("OnClick", function()
local name = namePopup.editbox:GetText() local name = namePopup.editbox:GetText()
if not name or name == "" then return end if not name or name == "" then return end
@@ -604,6 +620,24 @@ pfUI:RegisterModule("equipmentmanager", function()
pfUI.equipmentmanager.Refresh() pfUI.equipmentmanager.Refresh()
end) end)
-- Search box (bottom-left) filters the icon grid by name.
namePopup.searchLabel = namePopup:CreateFontString(nil, "OVERLAY", "GameFontNormal")
namePopup.searchLabel:SetPoint("BOTTOMLEFT", namePopup, "BOTTOMLEFT", 16, 18)
namePopup.searchLabel:SetText(SEARCH)
namePopup.search = CreateFrame("EditBox", "pfEqMgrIconSearch", namePopup, "InputBoxTemplate")
namePopup.search:SetSize(180, 20)
namePopup.search:SetPoint("LEFT", namePopup.searchLabel, "RIGHT", 10, 0)
namePopup.search:SetAutoFocus(false)
CreateBackdrop(namePopup.search)
namePopup.search:SetScript("OnEscapePressed", function() this:ClearFocus() end)
namePopup.search:SetScript("OnTextChanged", function()
searchText = strupper(strtrim(this:GetText()))
RebuildFilter()
if scrollbar then scrollbar:SetValue(0) end
pfUI.equipmentmanager.RefreshIconGrid()
end)
-- Assignment (not `local function`) so this fills in the forward -- Assignment (not `local function`) so this fills in the forward
-- declaration at the top of the module — closures created earlier -- declaration at the top of the module — closures created earlier
-- (row gear menu, "+ New Set" row, etc.) capture the same upvalue. -- (row gear menu, "+ New Set" row, etc.) capture the same upvalue.
@@ -612,26 +646,32 @@ pfUI:RegisterModule("equipmentmanager", function()
namePopup.editbox:SetText(prefillName or "") namePopup.editbox:SetText(prefillName or "")
EnsureProvider() EnsureProvider()
if prefillIcon then if prefillIcon then
local short = string.gsub(prefillIcon, "INTERFACE\\ICONS\\", "") -- Stored icons come back either as a full path or a bare basename
selectedIconPath = "INTERFACE\\ICONS\\" .. strupper(short) -- (see the row rendering in Refresh). Only prepend the prefix when
-- there's no path separator, so a full path isn't double-prefixed.
selectedIconPath = string.find(prefillIcon, "\\") and prefillIcon
or ("INTERFACE\\ICONS\\" .. prefillIcon)
else else
selectedIconPath = QUESTION_MARK selectedIconPath = QUESTION_MARK
end end
namePopup.search:SetText("")
if action == "rename" then if action == "rename" then
namePopup.title:SetText(T["Rename Set"] or "Rename Set")
iconScroll:Hide() iconScroll:Hide()
for _, b in ipairs(iconButtons) do b:Hide() end for _, b in ipairs(iconButtons) do b:Hide() end
namePopup.iconLabel:Hide() namePopup.iconLabel:Hide()
namePopup.selectedLabel:Hide() namePopup.selectedLabel:Hide()
namePopup.selectedPreview:Hide() namePopup.selectedPreview:Hide()
filterDropdown:Hide() filterDropdown:Hide()
namePopup.searchLabel:Hide()
namePopup.search:Hide()
else else
namePopup.title:SetText(action == "new" and (T["Name Set"] or "Name Set") or (T["Save Set"] or "Save Set"))
iconScroll:Show() iconScroll:Show()
namePopup.iconLabel:Show() namePopup.iconLabel:Show()
namePopup.selectedLabel:Show() namePopup.selectedLabel:Show()
namePopup.selectedPreview:Show() namePopup.selectedPreview:Show()
filterDropdown:Show() filterDropdown:Show()
namePopup.searchLabel:Show()
namePopup.search:Show()
end end
namePopup:Show() namePopup:Show()
if action ~= "rename" then pfUI.equipmentmanager.RefreshIconGrid() end if action ~= "rename" then pfUI.equipmentmanager.RefreshIconGrid() end
@@ -643,9 +683,13 @@ pfUI:RegisterModule("equipmentmanager", function()
-- ============================================================ -- ============================================================
local flyout = CreateFrame("Frame", "pfEqMgrFlyout", UIParent) local flyout = CreateFrame("Frame", "pfEqMgrFlyout", UIParent)
-- Everything tied to the EM sidecar closes with it: the popout arrows,
-- the per-slot flyout, and the name/icon popup. (OnShow re-shows the
-- popout arrows.)
frame:SetScript("OnHide", function() frame:SetScript("OnHide", function()
for _, b in ipairs(popoutButtons) do b:Hide() end for _, b in ipairs(popoutButtons) do b:Hide() end
flyout:Hide() flyout:Hide()
namePopup:Hide()
end) end)
flyout:SetFrameStrata("DIALOG") flyout:SetFrameStrata("DIALOG")
flyout:Hide() flyout:Hide()
@@ -676,7 +720,7 @@ pfUI:RegisterModule("equipmentmanager", function()
end end
end end
ClearCursor() ClearCursor()
UIErrorsFrame:AddMessage(EQUIPMENT_MANAGER_BAGS_FULL or "Your bags are full.", 1, .1, .1, 1) UIErrorsFrame:AddMessage(ERR_EQUIPMENT_MANAGER_BAGS_FULL, 1, .1, .1, 1)
end end
local function MakeFlyoutButton(i) local function MakeFlyoutButton(i)
@@ -692,11 +736,11 @@ pfUI:RegisterModule("equipmentmanager", function()
b:SetScript("OnEnter", function() b:SetScript("OnEnter", function()
GameTooltip:SetOwner(this, "ANCHOR_RIGHT") GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
if this.specialAction == "placeInBags" then if this.specialAction == "placeInBags" then
GameTooltip:SetText(EQUIPMENT_MANAGER_PLACE_IN_BAGS or "Place in Bags", 1, 1, 1) GameTooltip:SetText(EQUIPMENT_MANAGER_PLACE_IN_BAGS, 1, 1, 1)
elseif this.specialAction == "ignore" then elseif this.specialAction == "ignore" then
GameTooltip:SetText(EQUIPMENT_MANAGER_IGNORE_SLOT or "Ignore this slot", 1, 1, 1) GameTooltip:SetText(EQUIPMENT_MANAGER_IGNORE_SLOT, 1, 1, 1)
elseif this.specialAction == "unignore" then elseif this.specialAction == "unignore" then
GameTooltip:SetText(EQUIPMENT_MANAGER_UNIGNORE_SLOT or "Stop ignoring this slot", 1, 1, 1) GameTooltip:SetText(EQUIPMENT_MANAGER_UNIGNORE_SLOT, 1, 1, 1)
elseif this.bag then elseif this.bag then
GameTooltip:SetBagItem(this.bag, this.slot) GameTooltip:SetBagItem(this.bag, this.slot)
elseif this.invSlot then elseif this.invSlot then
@@ -704,7 +748,7 @@ pfUI:RegisterModule("equipmentmanager", function()
end end
GameTooltip:Show() GameTooltip:Show()
end) end)
b:SetScript("OnLeave", function() GameTooltip:Hide() end) b:SetScript("OnLeave", GameTooltip_Hide)
b:SetScript("OnClick", function() b:SetScript("OnClick", function()
if this.specialAction == "placeInBags" then if this.specialAction == "placeInBags" then
UnequipToBags(flyout.targetInvSlot) UnequipToBags(flyout.targetInvSlot)
@@ -809,7 +853,6 @@ pfUI:RegisterModule("equipmentmanager", function()
if num == 0 then if num == 0 then
flyout:Hide() flyout:Hide()
UIErrorsFrame:AddMessage(T["No matching items in bags"] or "No matching items in bags", 1, 1, 0, 1)
return return
end end
@@ -938,16 +981,6 @@ pfUI:RegisterModule("equipmentmanager", function()
end end
end end
-- Tie popout visibility to the EM sidecar. They appear when the
-- sidecar opens, hide when it closes, and the flyout closes too.
frame:HookScript("OnShow", function()
for _, b in ipairs(popoutButtons) do b:Show() end
end)
frame:HookScript("OnHide", function()
for _, b in ipairs(popoutButtons) do b:Hide() end
if flyout then flyout:Hide() end
end)
-- ============================================================ -- ============================================================
-- Refresh -- Refresh
-- ============================================================ -- ============================================================
+9 -4
View File
@@ -76,9 +76,14 @@ pfUI:RegisterModule("macroicons", function ()
picker.selectedPreview.tex:SetAllPoints(picker.selectedPreview) picker.selectedPreview.tex:SetAllPoints(picker.selectedPreview)
picker.selectedPreview.tex:SetTexCoord(.08, .92, .08, .92) picker.selectedPreview.tex:SetTexCoord(.08, .92, .08, .92)
picker.selectedLabel = picker:CreateFontString(nil, "OVERLAY", "GameFontNormal")
picker.selectedLabel:SetPoint("TOPRIGHT", picker, "TOPRIGHT", -14, -28)
picker.selectedLabel:SetText(ICON_SELECTION_TITLE_CURRENT)
picker.selectedLabel:SetTextColor(1, 0.82, 0)
picker.iconLabel = picker:CreateFontString(nil, "OVERLAY", "GameFontNormal") picker.iconLabel = picker:CreateFontString(nil, "OVERLAY", "GameFontNormal")
picker.iconLabel:SetPoint("TOPLEFT", picker, "TOPLEFT", 14, -100) picker.iconLabel:SetPoint("TOPLEFT", picker, "TOPLEFT", 14, -100)
picker.iconLabel:SetText(T["Choose an Icon:"] or "Choose an Icon:") picker.iconLabel:SetText(MACRO_POPUP_CHOOSE_ICON)
-- Icon grid + scroll -- Icon grid + scroll
local iconScroll = CreateFrame("ScrollFrame", "pfMacroIconScroll", picker, "FauxScrollFrameTemplate") local iconScroll = CreateFrame("ScrollFrame", "pfMacroIconScroll", picker, "FauxScrollFrameTemplate")
@@ -108,15 +113,15 @@ pfUI:RegisterModule("macroicons", function ()
end end
UIDropDownMenu_Initialize(filterDropdown, function() UIDropDownMenu_Initialize(filterDropdown, function()
local info local info
info = {}; info.text = T["All Icons"] or "All Icons"; info.value = "all" info = {}; info.text = ICON_FILTER_ALL; info.value = "all"
info.func = function() ApplyFilter("all") end info.func = function() ApplyFilter("all") end
info.checked = currentFilter == "all" info.checked = currentFilter == "all"
UIDropDownMenu_AddButton(info) UIDropDownMenu_AddButton(info)
info = {}; info.text = T["Spells"] or "Spells"; info.value = "spells" info = {}; info.text = ICON_FILTER_SPELL; info.value = "spells"
info.func = function() ApplyFilter("spells") end info.func = function() ApplyFilter("spells") end
info.checked = currentFilter == "spells" info.checked = currentFilter == "spells"
UIDropDownMenu_AddButton(info) UIDropDownMenu_AddButton(info)
info = {}; info.text = T["Items"] or "Items"; info.value = "items" info = {}; info.text = ICON_FILTER_ITEM; info.value = "items"
info.func = function() ApplyFilter("items") end info.func = function() ApplyFilter("items") end
info.checked = currentFilter == "items" info.checked = currentFilter == "items"
UIDropDownMenu_AddButton(info) UIDropDownMenu_AddButton(info)