Show loot history and the icon picker in ClassicAPI ScrollBoxes

pfUIScrollBoxListTemplate (api/ui-widgets.xml) is a WowScrollBoxList with
pfUIScrollBarTemplate beside it, 5px inside the frame, so a list's
backdrop goes on the frame itself. The addon list moves onto it and drops
the sibling backdrop frame.

Loot history builds a flat list of item rows and, under an expanded item,
player rows; the view sizes and indents them. The item frame array, the
player pool, the hand-placed rows and the scroll child re-attach are gone,
and the scroll position holds across roll updates.

The icon picker's FauxScrollFrame and 80 fixed buttons become a grid view
over the provider's icon indices. Picking an icon reinitializes the shown
buttons instead of redrawing the grid, and closing the popup drops the
grid's entries along with the provider.
This commit is contained in:
Brues
2026-10-30 00:47:07 -05:00
parent 796f20eadf
commit 3987cfb8a0
4 changed files with 157 additions and 181 deletions
+63 -73
View File
@@ -1252,7 +1252,7 @@ end
-- survives filter changes -- a spell icon you picked still saves after you -- 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. -- 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 -- parent the popup frame to attach the widgets to
-- extraType IconDataProviderExtraType.* seed (Spellbook / Equipment) -- extraType IconDataProviderExtraType.* seed (Spellbook / Equipment)
-- nameLabelText header shown above the name field -- 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:SetPoint("TOPLEFT", parent, "TOPLEFT", 14, -86)
parent.iconLabel:SetText(MACRO_POPUP_CHOOSE_ICON) parent.iconLabel:SetText(MACRO_POPUP_CHOOSE_ICON)
-- Icon grid + scroll -- Icon grid: the template keeps 5px around the grid and its 7px scroll bar,
local iconScroll = CreateFrame("ScrollFrame", name.."Scroll", parent, "FauxScrollFrameTemplate") -- and the grid leaves 4px before the bar
iconScroll:SetPoint("TOPLEFT", parent, "TOPLEFT", 14, -116) local gridWidth = 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) local gridHeight = 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) local grid = CreateFrame("Frame", name.."Icons", parent, "pfUIScrollBoxListTemplate")
grid:SetPoint("TOPLEFT", parent, "TOPLEFT", 9, -111)
local scrollbar = _G[name.."ScrollScrollBar"] grid:SetSize(gridWidth + 4 + 7 + 10, gridHeight + 10)
scrollbar:ClearAllPoints()
scrollbar:SetPoint("TOPLEFT", iconScroll, "TOPRIGHT", 8, -16)
scrollbar:SetPoint("BOTTOMLEFT", iconScroll, "BOTTOMRIGHT", 8, 16)
SkinScrollbar(scrollbar)
-- Filter dropdown: All / Spells / Items -- Filter dropdown: All / Spells / Items
local filterDropdown = CreateFrame("Frame", name.."Filter", parent, "UIDropDownMenuTemplate") local filterDropdown = CreateFrame("Frame", name.."Filter", parent, "UIDropDownMenuTemplate")
@@ -1367,38 +1363,54 @@ function pfUI.api.CreateIconPicker(name, parent, extraType, nameLabelText)
UIDropDownMenu_SetSelectedValue(filterDropdown, "all") UIDropDownMenu_SetSelectedValue(filterDropdown, "all")
SkinDropDown(filterDropdown) SkinDropDown(filterDropdown)
local iconButtons = {} -- the selected icon gets a gold border in the grid and shows in the preview
for r = 1, ICON_GRID_ROWS do local function UpdateSelection()
for c = 1, ICON_GRID_COLS do grid.ScrollBox:ReinitializeFrames()
local i = (r - 1) * ICON_GRID_COLS + c parent.selectedPreview.tex:SetTexture(selectedIconPath)
local btn = CreateFrame("Button", nil, parent) end
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)) 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) CreateBackdrop(btn)
btn.texture = btn:CreateTexture(nil, "ARTWORK") btn.texture = btn:CreateTexture(nil, "ARTWORK")
btn.texture:SetAllPoints(btn) btn.texture:SetAllPoints(btn)
btn.texture:SetTexCoord(.08, .92, .08, .92) btn.texture:SetTexCoord(.08, .92, .08, .92)
btn:SetScript("OnClick", function() btn:SetScript("OnClick", IconOnClick)
if this.iconIndex and provider then btn:SetScript("OnEnter", IconOnEnter)
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("OnLeave", GameTooltip_Hide) 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
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 -- Rebuild the search-filtered index list (provider indices whose icon
-- basename contains the search text); nil when the search box is empty. -- basename contains the search text); nil when the search box is empty.
function RebuildFilter() function RebuildFilter()
@@ -1416,38 +1428,17 @@ function pfUI.api.CreateIconPicker(name, parent, extraType, nameLabelText)
end end
end end
-- one grid entry per provider index the filter lets through, scrolled to the top
function RefreshIconGrid() function RefreshIconGrid()
EnsureProvider() EnsureProvider()
local numIcons = filtered and table.getn(filtered) or provider:GetNumIcons() if filtered then
local numRows = math.ceil(numIcons / ICON_GRID_COLS) grid.ScrollBox:SetDataProvider(CreateDataProviderWithAssignedKey(filtered, "index"))
FauxScrollFrame_Update(iconScroll, numRows, ICON_GRID_ROWS, ICON_BTN_SIZE + ICON_BTN_PAD) else
local offset = FauxScrollFrame_GetOffset(iconScroll) grid.ScrollBox:SetDataProvider(CreateDataProviderByIndexCount(provider:GetNumIcons()))
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
end end
parent.selectedPreview.tex:SetTexture(selectedIconPath) parent.selectedPreview.tex:SetTexture(selectedIconPath)
end 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. -- Search box (bottom-left) filters the grid by icon name.
parent.searchLabel = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal") parent.searchLabel = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
parent.searchLabel:SetPoint("BOTTOMLEFT", parent, "BOTTOMLEFT", 16, 18) 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() parent.search:SetScript("OnTextChanged", function()
searchText = strupper(strtrim(this:GetText())) searchText = strupper(strtrim(this:GetText()))
RebuildFilter() RebuildFilter()
scrollbar:SetValue(0)
RefreshIconGrid() RefreshIconGrid()
end) 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() parent:HookScript("OnHide", function()
if provider then provider:Release(); provider = nil end if provider then provider:Release(); provider = nil end
grid.ScrollBox:RemoveDataProvider()
end) end)
local handle = { editbox = parent.editbox, search = parent.search } 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.SetIcon(path) selectedIconPath = path or QUESTION_MARK end
function handle.Refresh() RefreshIconGrid() end function handle.Refresh() RefreshIconGrid() end
function handle.SetIconAreaShown(shown) function handle.SetIconAreaShown(shown)
local method = shown and "Show" or "Hide" grid:SetShown(shown)
iconScroll[method](iconScroll) parent.iconLabel:SetShown(shown)
for _, b in ipairs(iconButtons) do b[method](b) end parent.selectedLabel:SetShown(shown)
parent.iconLabel[method](parent.iconLabel) parent.selectedPreview:SetShown(shown)
parent.selectedLabel[method](parent.selectedLabel) filterDropdown:SetShown(shown)
parent.selectedPreview[method](parent.selectedPreview) parent.searchLabel:SetShown(shown)
filterDropdown[method](filterDropdown) parent.search:SetShown(shown)
parent.searchLabel[method](parent.searchLabel)
parent.search[method](parent.search)
end end
return handle return handle
end end
+22
View File
@@ -29,6 +29,28 @@
</Frames> </Frames>
</EventFrame> </EventFrame>
<!--
A WowScrollBoxList with pfUIScrollBarTemplate beside it, both 5px inside the
frame so CreateBackdrop(frame, nil, true) can frame them. Fill it with
ScrollUtil.InitScrollBoxListWithScrollBar(frame.ScrollBox, frame.ScrollBar, view).
-->
<Frame name="pfUIScrollBoxListTemplate" virtual="true">
<Frames>
<EventFrame parentKey="ScrollBar" inherits="pfUIScrollBarTemplate">
<Anchors>
<Anchor point="TOPRIGHT" x="-5" y="-5"/>
<Anchor point="BOTTOMRIGHT" x="-5" y="5"/>
</Anchors>
</EventFrame>
<Frame parentKey="ScrollBox" inherits="WowScrollBoxList">
<Anchors>
<Anchor point="TOPLEFT" x="5" y="-5"/>
<Anchor point="BOTTOMRIGHT" relativeKey="$parent.ScrollBar" relativePoint="BOTTOMLEFT"/>
</Anchors>
</Frame>
</Frames>
</Frame>
<!-- <!--
ClassicAPI's ScrollingEditBoxTemplate with pfUIScrollBarTemplate beside the ClassicAPI's ScrollingEditBoxTemplate with pfUIScrollBarTemplate beside the
text. The frame needs a name: SetFont(font, size, flags) names its font text. The frame needs a name: SetFont(font, size, flags) names its font
+11 -20
View File
@@ -133,7 +133,7 @@ pfUI:RegisterModule("addons", function ()
end end
end end
pfUI.addons.scroll:ReinitializeFrames() pfUI.addons.list.ScrollBox:ReinitializeFrames()
end end
-- addon profiles -- addon profiles
@@ -305,30 +305,21 @@ pfUI:RegisterModule("addons", function ()
end end
-- addon list: a ScrollBox keeps rows only for the addons in view -- addon list: a ScrollBox keeps rows only for the addons in view
pfUI.addons.scroll = CreateFrame("Frame", "pfAddonListScroll", pfUI.addons, "WowScrollBoxList") pfUI.addons.list = CreateFrame("Frame", "pfAddonList", pfUI.addons, "pfUIScrollBoxListTemplate")
pfUI.addons.scroll:SetSize(360, 410) pfUI.addons.list:SetSize(370, 420)
pfUI.addons.scroll:SetPoint("BOTTOM", 0, 10) pfUI.addons.list:SetPoint("BOTTOM", 0, 5)
CreateBackdrop(pfUI.addons.list, nil, true)
-- the ScrollBox clips its children, so the backdrop is a sibling local view = CreateScrollBoxListLinearView(5, 5, 5, 8)
pfUI.addons.scroll.backdrop = CreateFrame("Frame", nil, pfUI.addons)
pfUI.addons.scroll.backdrop:SetPoint("TOPLEFT", pfUI.addons.scroll, "TOPLEFT", -5, 5)
pfUI.addons.scroll.backdrop:SetPoint("BOTTOMRIGHT", pfUI.addons.scroll, "BOTTOMRIGHT", 5, -5)
CreateBackdrop(pfUI.addons.scroll.backdrop, nil, true)
local scrollbar = CreateFrame("EventFrame", nil, pfUI.addons, "pfUIScrollBarTemplate")
scrollbar:SetPoint("TOPRIGHT", pfUI.addons.scroll, "TOPRIGHT")
scrollbar:SetPoint("BOTTOMRIGHT", pfUI.addons.scroll, "BOTTOMRIGHT")
local view = CreateScrollBoxListLinearView(5, 5, 5, 15)
view:SetElementExtent(25) view:SetElementExtent(25)
view:SetElementInitializer("Button", InitRow) view:SetElementInitializer("Button", InitRow)
ScrollUtil.InitScrollBoxListWithScrollBar(pfUI.addons.scroll, scrollbar, view) ScrollUtil.InitScrollBoxListWithScrollBar(pfUI.addons.list.ScrollBox, pfUI.addons.list.ScrollBar, view)
pfUI.addons.scroll:SetDataProvider(CreateDataProvider(addons)) pfUI.addons.list.ScrollBox:SetDataProvider(CreateDataProvider(addons))
-- a load-on-demand addon that loads brightens its row -- a load-on-demand addon that loads brightens its row
pfUI.addons.scroll:RegisterEvent("ADDON_LOADED") pfUI.addons.list:RegisterEvent("ADDON_LOADED")
pfUI.addons.scroll:SetScript("OnEvent", function(self) pfUI.addons.list:SetScript("OnEvent", function(self)
self:ReinitializeFrames() self.ScrollBox:ReinitializeFrames()
end) end)
end) end)
+61 -88
View File
@@ -1,9 +1,9 @@
pfUI:RegisterModule("loothistory", function () pfUI:RegisterModule("loothistory", function ()
local rawborder, border = GetBorderSize() local rawborder, border = GetBorderSize()
-- Layout -- Layout (rows are 2px apart)
local ITEM_H, PLAYER_H = 24, 18 local ITEM_H, PLAYER_H = 24, 16
local ITEM_W, PLAYER_W = 350, 330 local PLAYER_INDENT = 18
-- rollType constants returned by C_LootHistory.GetPlayerInfo (0/1/2; vanilla -- rollType constants returned by C_LootHistory.GetPlayerInfo (0/1/2; vanilla
-- has no disenchant roll). -- has no disenchant roll).
@@ -86,30 +86,24 @@ pfUI:RegisterModule("loothistory", function ()
pfUI.loothistory.clear:SetText(T["Clear"]) pfUI.loothistory.clear:SetText(T["Clear"])
pfUI.loothistory.clear:SetScript("OnClick", function() C_LootHistory.Clear() end) pfUI.loothistory.clear:SetScript("OnClick", function() C_LootHistory.Clear() end)
-- scroll frame -- ==========================================================================
pfUI.loothistory.scroll = CreateScrollFrame("pfLootHistoryScroll", pfUI.loothistory) -- List: a row per item and, under an expanded item, a row per player
pfUI.loothistory.scroll:SetSize(360, 440) -- ==========================================================================
pfUI.loothistory.scroll:SetPoint("BOTTOM", 0, 10) local list = CreateFrame("Frame", "pfLootHistoryList", pfUI.loothistory, "pfUIScrollBoxListTemplate")
list:SetSize(370, 450)
pfUI.loothistory.scroll.backdrop = CreateFrame("Frame", nil, pfUI.loothistory.scroll) list:SetPoint("BOTTOM", 0, 5)
pfUI.loothistory.scroll.backdrop:SetFrameLevel(1) CreateBackdrop(list, nil, true)
pfUI.loothistory.scroll.backdrop:SetPoint("TOPLEFT", pfUI.loothistory.scroll, "TOPLEFT", -5, 5)
pfUI.loothistory.scroll.backdrop:SetPoint("BOTTOMRIGHT", pfUI.loothistory.scroll, "BOTTOMRIGHT", 5, -5)
CreateBackdrop(pfUI.loothistory.scroll.backdrop, nil, true)
local list = CreateScrollChild("pfLootHistoryList", pfUI.loothistory.scroll)
pfUI.loothistory.list = list pfUI.loothistory.list = list
-- ==========================================================================
-- Frame pools
-- ==========================================================================
local itemFrames = {}
local FullUpdate -- forward declaration (toggle handlers call it) local FullUpdate -- forward declaration (toggle handlers call it)
local function CreateItemFrame() local function ToggleExpanded(f)
local f = CreateFrame("Button", nil, list) local id = f.rollID
f:SetSize(ITEM_W, ITEM_H) if id then expanded[id] = not expanded[id]; FullUpdate() end
end
-- one-time setup of a pooled item row
local function SetupItemRow(f)
f:SetBackdrop(pfUI.backdrop_hover) f:SetBackdrop(pfUI.backdrop_hover)
f:SetBackdropBorderColor(1, 1, 1, .04) f:SetBackdropBorderColor(1, 1, 1, .04)
f:EnableMouse(1) f:EnableMouse(1)
@@ -118,10 +112,7 @@ pfUI:RegisterModule("loothistory", function ()
f.toggle = CreateFrame("Button", nil, f) f.toggle = CreateFrame("Button", nil, f)
f.toggle:SetSize(14, 14) f.toggle:SetSize(14, 14)
f.toggle:SetPoint("LEFT", 4, 0) f.toggle:SetPoint("LEFT", 4, 0)
f.toggle:SetScript("OnClick", function() f.toggle:SetScript("OnClick", function() ToggleExpanded(f) end)
local id = f.rollID
if id then expanded[id] = not expanded[id]; FullUpdate() end
end)
-- icon + quality-colored border -- icon + quality-colored border
f.iconbg = CreateFrame("Frame", nil, f) f.iconbg = CreateFrame("Frame", nil, f)
@@ -138,18 +129,18 @@ pfUI:RegisterModule("loothistory", function ()
f.winicon:SetSize(14, 14) f.winicon:SetSize(14, 14)
f.winicon:SetPoint("RIGHT", f, "RIGHT", -6, 0) f.winicon:SetPoint("RIGHT", f, "RIGHT", -6, 0)
f.winroll = f:CreateFontString("Status", "OVERLAY", "GameFontNormal") f.winroll = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
f.winroll:SetFont(pfUI.font_default, C.global.font_size, "OUTLINE") f.winroll:SetFont(pfUI.font_default, C.global.font_size, "OUTLINE")
f.winroll:SetPoint("RIGHT", f.winicon, "LEFT", -2, 0) f.winroll:SetPoint("RIGHT", f.winicon, "LEFT", -2, 0)
f.winroll:SetTextColor(1, 1, 1, 1) f.winroll:SetTextColor(1, 1, 1, 1)
f.winname = f:CreateFontString("Status", "OVERLAY", "GameFontNormal") f.winname = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
f.winname:SetFont(pfUI.font_default, C.global.font_size, "OUTLINE") f.winname:SetFont(pfUI.font_default, C.global.font_size, "OUTLINE")
f.winname:SetPoint("RIGHT", f.winroll, "LEFT", -4, 0) f.winname:SetPoint("RIGHT", f.winroll, "LEFT", -4, 0)
f.winname:SetJustifyH("RIGHT") f.winname:SetJustifyH("RIGHT")
-- item name (leaves room on the right for the winner block) -- item name (leaves room on the right for the winner block)
f.name = f:CreateFontString("Status", "OVERLAY", "GameFontNormal") f.name = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
f.name:SetFont(pfUI.font_default, C.global.font_size, "OUTLINE") f.name:SetFont(pfUI.font_default, C.global.font_size, "OUTLINE")
f.name:SetPoint("LEFT", f.iconbg, "RIGHT", 5, 0) f.name:SetPoint("LEFT", f.iconbg, "RIGHT", 5, 0)
f.name:SetPoint("RIGHT", f, "RIGHT", -100, 0) f.name:SetPoint("RIGHT", f, "RIGHT", -100, 0)
@@ -167,20 +158,13 @@ pfUI:RegisterModule("loothistory", function ()
this:SetBackdropBorderColor(1, 1, 1, .04) this:SetBackdropBorderColor(1, 1, 1, .04)
GameTooltip:Hide() GameTooltip:Hide()
end) end)
f:SetScript("OnClick", function() f:SetScript("OnClick", function() ToggleExpanded(f) end)
local id = this.rollID
if id then expanded[id] = not expanded[id]; FullUpdate() end
end)
return f
end end
local function CreatePlayerFrame() -- one-time setup of a pooled player row
local f = CreateFrame("Frame", nil, list) local function SetupPlayerRow(f)
f:SetSize(PLAYER_W, PLAYER_H)
-- name is indented to leave room for the winner checkmark on its left -- name is indented to leave room for the winner checkmark on its left
f.name = f:CreateFontString("Status", "OVERLAY", "GameFontNormal") f.name = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
f.name:SetFont(pfUI.font_default, C.global.font_size, "OUTLINE") f.name:SetFont(pfUI.font_default, C.global.font_size, "OUTLINE")
f.name:SetPoint("LEFT", 20, 0) f.name:SetPoint("LEFT", 20, 0)
f.name:SetJustifyH("LEFT") f.name:SetJustifyH("LEFT")
@@ -189,7 +173,7 @@ pfUI:RegisterModule("loothistory", function ()
f.rollicon:SetSize(16, 16) f.rollicon:SetSize(16, 16)
f.rollicon:SetPoint("RIGHT", -4, 0) f.rollicon:SetPoint("RIGHT", -4, 0)
f.rolltext = f:CreateFontString("Status", "OVERLAY", "GameFontNormal") f.rolltext = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
f.rolltext:SetFont(pfUI.font_default, C.global.font_size, "OUTLINE") f.rolltext:SetFont(pfUI.font_default, C.global.font_size, "OUTLINE")
f.rolltext:SetPoint("RIGHT", f.rollicon, "LEFT", -3, 0) f.rolltext:SetPoint("RIGHT", f.rollicon, "LEFT", -3, 0)
f.rolltext:SetTextColor(1, 1, 1, 1) f.rolltext:SetTextColor(1, 1, 1, 1)
@@ -199,15 +183,8 @@ pfUI:RegisterModule("loothistory", function ()
f.winmark:SetSize(16, 16) f.winmark:SetSize(16, 16)
f.winmark:SetTexture(WINMARK) f.winmark:SetTexture(WINMARK)
f.winmark:SetPoint("RIGHT", f.name, "LEFT", -1, 0) f.winmark:SetPoint("RIGHT", f.name, "LEFT", -1, 0)
return f
end end
local playerPool = CreateObjectPool(CreatePlayerFrame, function(_, pf)
pf:Hide()
pf:ClearAllPoints()
end)
local function SetToggleTexture(toggle, isExpanded) local function SetToggleTexture(toggle, isExpanded)
if isExpanded then if isExpanded then
toggle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up") toggle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up")
@@ -221,13 +198,13 @@ pfUI:RegisterModule("loothistory", function ()
-- ========================================================================== -- ==========================================================================
-- Rendering -- Rendering
-- ========================================================================== -- ==========================================================================
local function UpdateItemFrame(f, i) local function InitItemRow(f, row)
local rollID, itemLink, numPlayers, isDone, winnerIdx = C_LootHistory.GetItem(i) if not f.toggle then SetupItemRow(f) end
local i = row.item
local rollID, itemLink, _, isDone, winnerIdx = C_LootHistory.GetItem(i)
f.rollID = rollID f.rollID = rollID
f.itemIdx = i
f.itemLink = itemLink f.itemLink = itemLink
f.numPlayers = numPlayers or 0
f.isDone = isDone
local isExpanded = rollID and expanded[rollID] local isExpanded = rollID and expanded[rollID]
SetToggleTexture(f.toggle, isExpanded) SetToggleTexture(f.toggle, isExpanded)
@@ -279,7 +256,10 @@ pfUI:RegisterModule("loothistory", function ()
end end
end end
local function RenderPlayerFrame(pf, name, class, rollType, roll, isWinner) local function InitPlayerRow(pf, row)
if not pf.name then SetupPlayerRow(pf) end
local name, class, rollType, roll, isWinner = C_LootHistory.GetPlayerInfo(row.item, row.player)
pf.name:SetText(name or UNKNOWN) pf.name:SetText(name or UNKNOWN)
pf.name:SetTextColor(PFUI_CLASS_COLORS[class]:GetRGB()) pf.name:SetTextColor(PFUI_CLASS_COLORS[class]:GetRGB())
@@ -289,6 +269,22 @@ pfUI:RegisterModule("loothistory", function ()
if isWinner then pf.winmark:Show() else pf.winmark:Hide() end if isWinner then pf.winmark:Show() else pf.winmark:Hide() end
end end
local view = CreateScrollBoxListLinearView(2, 2, 4, 4, 2)
view:SetElementFactory(function(factory, row)
if row.player then
factory("Frame", InitPlayerRow)
else
factory("Button", InitItemRow)
end
end)
view:SetElementExtentCalculator(function(_, row)
return row.player and PLAYER_H or ITEM_H
end)
view:SetElementIndentCalculator(function(row)
return row.player and PLAYER_INDENT or 0
end)
ScrollUtil.InitScrollBoxListWithScrollBar(list.ScrollBox, list.ScrollBar, view)
-- A player row is worth showing while the roll is undecided (see everyone), -- A player row is worth showing while the roll is undecided (see everyone),
-- or afterwards only if they actually rolled or it's you (hide the passers' -- or afterwards only if they actually rolled or it's you (hide the passers'
-- noise on a decided roll) — mirrors Blizzard's ShouldDisplayPlayer. -- noise on a decided roll) — mirrors Blizzard's ShouldDisplayPlayer.
@@ -298,46 +294,23 @@ pfUI:RegisterModule("loothistory", function ()
function FullUpdate() function FullUpdate()
if not pfUI.loothistory:IsShown() then return end if not pfUI.loothistory:IsShown() then return end
playerPool:ReleaseAll()
local num = C_LootHistory.GetNumItems() local rows = {}
local y = -2 for i = 1, C_LootHistory.GetNumItems() do
local rollID, _, numPlayers, isDone = C_LootHistory.GetItem(i)
table.insert(rows, { item = i })
for i = 1, num do if rollID and expanded[rollID] then
local f = itemFrames[i] or CreateItemFrame() for p = 1, numPlayers or 0 do
itemFrames[i] = f local _, _, _, roll, _, isMe = C_LootHistory.GetPlayerInfo(i, p)
UpdateItemFrame(f, i) if ShouldDisplayPlayer(isDone, roll, isMe) then
f:ClearAllPoints() table.insert(rows, { item = i, player = p })
f:SetPoint("TOPLEFT", list, "TOPLEFT", 4, y)
f:Show()
y = y - ITEM_H - 2
if f.rollID and expanded[f.rollID] then
for p = 1, f.numPlayers do
local name, class, rollType, roll, isWinner, isMe = C_LootHistory.GetPlayerInfo(i, p)
if ShouldDisplayPlayer(f.isDone, roll, isMe) then
local pf = playerPool:Acquire()
RenderPlayerFrame(pf, name, class, rollType, roll, isWinner)
pf:ClearAllPoints()
pf:SetPoint("TOPLEFT", list, "TOPLEFT", 22, y)
pf:Show()
y = y - PLAYER_H
end end
end end
y = y - 2
end end
end end
for i = num + 1, table.getn(itemFrames) do list.ScrollBox:SetDataProvider(CreateDataProvider(rows), ScrollBoxConstants.RetainScrollPosition)
itemFrames[i]:Hide()
end
-- Resize the scroll child and re-attach it: SetHeight alone on a
-- SetAllPoints'd child doesn't make the ScrollFrame recompute its scroll
-- range, so a dynamically-grown list wouldn't scroll until a /reload.
list:SetHeight(math.max(1, -y + 2))
pfUI.loothistory.scroll:SetScrollChild(list)
pfUI.loothistory.scroll:UpdateScrollState()
end end
pfUI.loothistory:SetScript("OnShow", function() FullUpdate() end) pfUI.loothistory:SetScript("OnShow", function() FullUpdate() end)