diff --git a/api/ui-widgets.lua b/api/ui-widgets.lua
index f431b99b..4fba4205 100644
--- a/api/ui-widgets.lua
+++ b/api/ui-widgets.lua
@@ -1252,7 +1252,7 @@ end
-- survives filter changes -- a spell icon you picked still saves after you
-- switch the filter to "Items" and it drops out of the visible grid.
--
--- name global-name prefix for the scroll frame and editboxes
+-- name global-name prefix for the icon grid and editboxes
-- parent the popup frame to attach the widgets to
-- extraType IconDataProviderExtraType.* seed (Spellbook / Equipment)
-- nameLabelText header shown above the name field
@@ -1322,17 +1322,13 @@ function pfUI.api.CreateIconPicker(name, parent, extraType, nameLabelText)
parent.iconLabel:SetPoint("TOPLEFT", parent, "TOPLEFT", 14, -86)
parent.iconLabel:SetText(MACRO_POPUP_CHOOSE_ICON)
- -- Icon grid + scroll
- local iconScroll = CreateFrame("ScrollFrame", name.."Scroll", parent, "FauxScrollFrameTemplate")
- iconScroll:SetPoint("TOPLEFT", parent, "TOPLEFT", 14, -116)
- 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)
-
- local scrollbar = _G[name.."ScrollScrollBar"]
- scrollbar:ClearAllPoints()
- scrollbar:SetPoint("TOPLEFT", iconScroll, "TOPRIGHT", 8, -16)
- scrollbar:SetPoint("BOTTOMLEFT", iconScroll, "BOTTOMRIGHT", 8, 16)
- SkinScrollbar(scrollbar)
+ -- Icon grid: the template keeps 5px around the grid and its 7px scroll bar,
+ -- and the grid leaves 4px before the bar
+ local gridWidth = ICON_GRID_COLS * (ICON_BTN_SIZE + ICON_BTN_PAD) - ICON_BTN_PAD
+ local gridHeight = ICON_GRID_ROWS * (ICON_BTN_SIZE + ICON_BTN_PAD) - ICON_BTN_PAD
+ local grid = CreateFrame("Frame", name.."Icons", parent, "pfUIScrollBoxListTemplate")
+ grid:SetPoint("TOPLEFT", parent, "TOPLEFT", 9, -111)
+ grid:SetSize(gridWidth + 4 + 7 + 10, gridHeight + 10)
-- Filter dropdown: All / Spells / Items
local filterDropdown = CreateFrame("Frame", name.."Filter", parent, "UIDropDownMenuTemplate")
@@ -1367,38 +1363,54 @@ function pfUI.api.CreateIconPicker(name, parent, extraType, nameLabelText)
UIDropDownMenu_SetSelectedValue(filterDropdown, "all")
SkinDropDown(filterDropdown)
- local iconButtons = {}
- for r = 1, ICON_GRID_ROWS do
- for c = 1, ICON_GRID_COLS do
- local i = (r - 1) * ICON_GRID_COLS + c
- local btn = CreateFrame("Button", nil, parent)
- btn:SetSize(ICON_BTN_SIZE, ICON_BTN_SIZE)
- btn:SetPoint("TOPLEFT", iconScroll, "TOPLEFT", (c-1) * (ICON_BTN_SIZE + ICON_BTN_PAD), -(r-1) * (ICON_BTN_SIZE + ICON_BTN_PAD))
+ -- the selected icon gets a gold border in the grid and shows in the preview
+ local function UpdateSelection()
+ grid.ScrollBox:ReinitializeFrames()
+ parent.selectedPreview.tex:SetTexture(selectedIconPath)
+ end
+
+ local function IconOnClick()
+ local path = provider:GetIconByIndex(this.iconIndex)
+ if path then selectedIconPath = path end
+ UpdateSelection()
+ end
+
+ local function IconOnEnter()
+ local path = provider:GetIconByIndex(this.iconIndex)
+ if type(path) == "string" then
+ GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
+ GameTooltip:SetText(IconKey(path), 1, 1, 1)
+ GameTooltip:Show()
+ end
+ end
+
+ local function InitIconButton(btn, icon)
+ -- one-time setup of a pooled button
+ if not btn.texture then
CreateBackdrop(btn)
btn.texture = btn:CreateTexture(nil, "ARTWORK")
btn.texture:SetAllPoints(btn)
btn.texture:SetTexCoord(.08, .92, .08, .92)
- btn:SetScript("OnClick", function()
- if this.iconIndex and provider then
- local path = provider:GetIconByIndex(this.iconIndex)
- if path then selectedIconPath = path end
- RefreshIconGrid()
- end
- end)
- btn:SetScript("OnEnter", function()
- if not this.iconIndex or not provider then return end
- local path = provider:GetIconByIndex(this.iconIndex)
- if type(path) == "string" then
- GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
- GameTooltip:SetText(IconKey(path), 1, 1, 1)
- GameTooltip:Show()
- end
- end)
+ btn:SetScript("OnClick", IconOnClick)
+ btn:SetScript("OnEnter", IconOnEnter)
btn:SetScript("OnLeave", GameTooltip_Hide)
- iconButtons[i] = btn
+ end
+
+ btn.iconIndex = icon.index
+ local path = provider:GetIconByIndex(icon.index)
+ btn.texture:SetTexture(path)
+ if IconKey(path) == IconKey(selectedIconPath) then
+ btn.backdrop:SetBackdropBorderColor(1, 0.82, 0, 1)
+ else
+ btn.backdrop:SetBackdropBorderColor(pfUI.cache.er, pfUI.cache.eg, pfUI.cache.eb, pfUI.cache.ea)
end
end
+ local view = CreateScrollBoxListGridView(ICON_GRID_COLS, 0, 0, 0, 4, ICON_BTN_PAD, ICON_BTN_PAD)
+ view:SetElementSize(ICON_BTN_SIZE, ICON_BTN_SIZE)
+ view:SetElementInitializer("Button", InitIconButton)
+ ScrollUtil.InitScrollBoxListWithScrollBar(grid.ScrollBox, grid.ScrollBar, view)
+
-- Rebuild the search-filtered index list (provider indices whose icon
-- basename contains the search text); nil when the search box is empty.
function RebuildFilter()
@@ -1416,38 +1428,17 @@ function pfUI.api.CreateIconPicker(name, parent, extraType, nameLabelText)
end
end
+ -- one grid entry per provider index the filter lets through, scrolled to the top
function RefreshIconGrid()
EnsureProvider()
- local numIcons = filtered and table.getn(filtered) or provider:GetNumIcons()
- local numRows = math.ceil(numIcons / ICON_GRID_COLS)
- FauxScrollFrame_Update(iconScroll, numRows, ICON_GRID_ROWS, ICON_BTN_SIZE + ICON_BTN_PAD)
- local offset = FauxScrollFrame_GetOffset(iconScroll)
- for i = 1, ICON_GRID_ROWS * ICON_GRID_COLS do
- local listIdx = i + offset * ICON_GRID_COLS
- local btn = iconButtons[i]
- if listIdx <= numIcons then
- btn:Show()
- local providerIdx = filtered and filtered[listIdx] or listIdx
- btn.iconIndex = providerIdx
- local path = provider:GetIconByIndex(providerIdx)
- btn.texture:SetTexture(path)
- if IconKey(path) == IconKey(selectedIconPath) then
- btn.backdrop:SetBackdropBorderColor(1, 0.82, 0, 1)
- else
- btn.backdrop:SetBackdropBorderColor(pfUI.cache.er, pfUI.cache.eg, pfUI.cache.eb, pfUI.cache.ea)
- end
- else
- btn:Hide()
- btn.iconIndex = nil
- end
+ if filtered then
+ grid.ScrollBox:SetDataProvider(CreateDataProviderWithAssignedKey(filtered, "index"))
+ else
+ grid.ScrollBox:SetDataProvider(CreateDataProviderByIndexCount(provider:GetNumIcons()))
end
parent.selectedPreview.tex:SetTexture(selectedIconPath)
end
- iconScroll:SetScript("OnVerticalScroll", function()
- FauxScrollFrame_OnVerticalScroll(ICON_BTN_SIZE + ICON_BTN_PAD, function() RefreshIconGrid() end)
- end)
-
-- Search box (bottom-left) filters the grid by icon name.
parent.searchLabel = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
parent.searchLabel:SetPoint("BOTTOMLEFT", parent, "BOTTOMLEFT", 16, 18)
@@ -1462,13 +1453,14 @@ function pfUI.api.CreateIconPicker(name, parent, extraType, nameLabelText)
parent.search:SetScript("OnTextChanged", function()
searchText = strupper(strtrim(this:GetText()))
RebuildFilter()
- scrollbar:SetValue(0)
RefreshIconGrid()
end)
- -- Release the provider when the popup closes so its icon cache GCs.
+ -- Release the provider when the popup closes so its icon cache GCs, and
+ -- the grid's entries that index into it.
parent:HookScript("OnHide", function()
if provider then provider:Release(); provider = nil end
+ grid.ScrollBox:RemoveDataProvider()
end)
local handle = { editbox = parent.editbox, search = parent.search }
@@ -1476,15 +1468,13 @@ function pfUI.api.CreateIconPicker(name, parent, extraType, nameLabelText)
function handle.SetIcon(path) selectedIconPath = path or QUESTION_MARK end
function handle.Refresh() RefreshIconGrid() end
function handle.SetIconAreaShown(shown)
- local method = shown and "Show" or "Hide"
- iconScroll[method](iconScroll)
- for _, b in ipairs(iconButtons) do b[method](b) end
- parent.iconLabel[method](parent.iconLabel)
- parent.selectedLabel[method](parent.selectedLabel)
- parent.selectedPreview[method](parent.selectedPreview)
- filterDropdown[method](filterDropdown)
- parent.searchLabel[method](parent.searchLabel)
- parent.search[method](parent.search)
+ grid:SetShown(shown)
+ parent.iconLabel:SetShown(shown)
+ parent.selectedLabel:SetShown(shown)
+ parent.selectedPreview:SetShown(shown)
+ filterDropdown:SetShown(shown)
+ parent.searchLabel:SetShown(shown)
+ parent.search:SetShown(shown)
end
return handle
end
diff --git a/api/ui-widgets.xml b/api/ui-widgets.xml
index a9a02407..981347de 100644
--- a/api/ui-widgets.xml
+++ b/api/ui-widgets.xml
@@ -29,6 +29,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+