Files
pfUI/modules/macroicons.lua
T
brues-code 41b77a5728 Add the macro icon picker and improve the equipment manager (#35)
* Add pfUI-native macro icon picker

Replace Blizzard's MacroPopupFrame (the name + icon dialog) with a
custom pfUI picker driven by IconDataProviderMixin, so the full spell +
item + loose icon set is available instead of the stock spell-only list.
It has a searchable, filterable icon grid and saves through
C_Macro.CreateMacro / C_Macro.EditMacro, which take the icon as a texture
string -- so arbitrary icons (including index-less INV_* item icons)
persist. The macro-frame API is identical on the modern (Turtle/Octo)
and stock-vanilla macro UIs, so the picker works on both with no client
detection.

The new macroicons module takes over the New / Change-Icon buttons and
retires the stock popup; the blizzard macro skin now only skins
MacroPopupFrame when that module is disabled.

* Gate the macro icon hook behind a config flag

Run the Blizzard_MacroUI hook only when C.disabled["macroicons"] is
"1".

* 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.

* Replace the row hover poll with OnLeave handlers

The gear button sits inside the set row's rectangle, so MouseIsOver(row)
is true for both. Show the gear on row enter. Hide it from a shared
OnLeave on the row and the gear when the cursor leaves the row. This
removes the per-frame OnUpdate poll.

* Handle missing C_Macro.CreateMacro API

Add guards to detect if C_Macro.CreateMacro is unavailable. The macroicons module now returns early if the API doesn't exist, and turtle-wow.lua uses the alternative Blizzard_MacroUI fallback path in such cases.

* Remove the macro picker title and shrink the window

Delete the title font string and its SetText calls. Move every
top-anchored element up 14px and shrink the window height from 498 to
484. The OK, Cancel, and search controls are bottom-anchored, so they
keep their spacing to the grid.

* bump ClassicAPI min version to 1.9.3

* Extract a shared icon picker widget

The macro icon picker and the equipment manager's name/icon popup carried
near-identical copies of the icon grid, All/Spells/Items filter, name search,
and the IconDataProvider state machine. Pull that into a single
pfUI.api.CreateIconPicker helper; each module keeps only its own frame shell,
buttons, and save flow.

Also fix the grid tooltip: pass white to GameTooltip:SetText (it defaults to
red) and derive the icon name with the case-insensitive basename key so
mixed-case provider paths show a clean name instead of the full path.
2026-08-05 22:33:37 -05:00

129 lines
5.0 KiB
Lua

-- Macro icon picker
-- Replaces Blizzard's MacroPopupFrame (the "name + icon" dialog opened by the
-- New / Change-Icon buttons) with a pfUI-native picker driven by
-- IconDataProviderMixin, so the full spell + item + loose icon set is
-- available instead of the stock spell-only list. Saving goes through
-- C_Macro.CreateMacro / C_Macro.EditMacro, which take the icon as a texture
-- string -- so arbitrary icons (including index-less INV_* item icons) persist
-- on both the modern (Turtle/Octo) and stock-vanilla macro UIs. The surrounding
-- MacroFrame (list + body editor) is Blizzard's, already skinned elsewhere.
pfUI:RegisterModule("macroicons", function ()
HookAddonOrVariable("Blizzard_MacroUI", function()
-- ============================================================
-- Popup frame
-- ============================================================
local picker = CreateFrame("Frame", "pfMacroIconPicker", UIParent)
picker:SetFrameStrata("DIALOG")
picker:SetSize(472, 484)
-- Starts anchored to the right of the macro panel (re-anchored at open
-- once the skin's backdrop exists); dragging pins it in place after.
picker:SetPoint("BOTTOMLEFT", MacroFrame, "BOTTOMRIGHT", 8, 0)
picker:Hide()
CreateBackdrop(picker, nil, nil, .9)
CreateBackdropShadow(picker)
picker:EnableMouse(true)
picker:SetMovable(true)
picker:RegisterForDrag("LeftButton")
picker:SetScript("OnDragStart", function() this:StartMoving() end)
picker:SetScript("OnDragStop", function()
this:StopMovingOrSizing()
this.userMoved = true
end)
-- Spellbook seed leads the grid with class-relevant spell/talent icons.
local iconPicker = CreateIconPicker("pfMacroIcon", picker,
IconDataProviderExtraType.Spellbook, MACRO_POPUP_TEXT)
-- ============================================================
-- Open / save
-- ============================================================
-- Blizzard's popup disables these while it is open; mirror that so the
-- underlying frame can't be double-driven, then let MacroFrame_Update
-- restore the correct states on close.
local function SetMacroButtons(enabled)
local m = enabled and "Enable" or "Disable"
MacroNewButton[m](MacroNewButton)
MacroEditButton[m](MacroEditButton)
MacroDeleteButton[m](MacroDeleteButton)
end
local function OpenMacroPopup(mode)
if mode == "edit" and MacroFrame.selectedMacro then
picker.mode = "edit"
local name, texture = GetMacroInfo(MacroFrame.selectedMacro)
picker.editbox:SetText(name or "")
iconPicker.SetIcon(texture)
else
picker.mode = "new"
picker.editbox:SetText("")
iconPicker.SetIcon(nil)
end
picker.search:SetText("")
if not picker.userMoved then
picker:ClearAllPoints()
picker:SetPoint("BOTTOMLEFT", MacroFrame.backdrop or MacroFrame, "BOTTOMRIGHT", 8, 0)
end
SetMacroButtons(false)
picker:Show()
picker.editbox:SetFocus()
iconPicker.Refresh()
end
local function SaveMacroPopup()
local text = strtrim(picker.editbox:GetText())
if text == "" then return end
local icon = iconPicker.GetIcon()
if picker.mode == "edit" and MacroFrame.selectedMacro then
C_Macro.EditMacro(MacroFrame.selectedMacro, text, icon, nil)
MacroFrame_SelectMacro(MacroFrame.selectedMacro)
else
local idx = C_Macro.CreateMacro(text, icon, nil, (MacroFrame.macroBase or 0) > 0)
if idx then MacroFrame_SelectMacro(idx) end
end
picker:Hide()
end
picker:SetScript("OnHide", function() MacroFrame_Update() end)
picker.editbox:SetScript("OnEnterPressed", SaveMacroPopup)
picker.editbox:SetScript("OnEscapePressed", function() picker:Hide() end)
-- OK / Cancel
local okay = CreateFrame("Button", "pfMacroIconPickerOkay", picker, "UIPanelButtonTemplate")
okay:SetSize(80, 22)
okay:SetText(OKAY)
okay:SetScript("OnClick", SaveMacroPopup)
SkinButton(okay)
local cancel = CreateFrame("Button", "pfMacroIconPickerCancel", picker, "UIPanelButtonTemplate")
cancel:SetSize(80, 22)
cancel:SetText(CANCEL)
cancel:SetPoint("BOTTOMRIGHT", picker, "BOTTOMRIGHT", -14, 12)
cancel:SetScript("OnClick", function() picker:Hide() end)
SkinButton(cancel)
-- Okay | Cancel, both anchored to the bottom-right corner.
okay:SetPoint("BOTTOMRIGHT", cancel, "BOTTOMLEFT", -6, 0)
-- ============================================================
-- Take over the New / Change-Icon buttons; retire Blizzard's popup
-- ============================================================
MacroNewButton:SetScript("OnClick", function()
MacroFrame_SaveMacro()
OpenMacroPopup("new")
end)
MacroEditButton:SetScript("OnClick", function()
MacroFrame_SaveMacro()
OpenMacroPopup("edit")
end)
-- Closing the macro window takes the picker with it.
MacroFrame:HookScript("OnHide", function() picker:Hide() end)
end)
end)