Updating SCrollFrame content without reloading the UI
I started working with Scrolling frames yesterday. I am using a standard UIPanaelScrollBar/frame template with SetScrollChild, etc. I am not working with FauxScrollFrame. I've created and setup a functional scrolling list using items in my bags as test data just to make sure it's all working as intended and on initial load, everything is working great. However, my problem has been trying to update the scrollframe content data without having to reload the UI.
Right now, I have my "content" generated by looping through my bags, if I try to run that same bit of code again, and resetting "scrollframe.content = content" I just get weirdness.
I've been googling for a while and I have found numerous examples of how to setup a scrollFrame, I haven't found anything on updating the content.
Can anyone help me or point me in the right direction?
EDIT
I figured it out, by hiding and reusing old frames... here is the code. basically it clears the content frame by hiding it's child frames, it saves a reference to the hidden frame so it can be used later in update()
Code:
local spacing = 1
local maxValue = 0
local step = 25
local frame = CreateFrame("Frame", "Scroller", UIParent)
local scrollframe = CreateFrame("ScrollFrame", "scroll_frame", frame)
local scrollbar = CreateFrame("Slider", "scroll_bar", scrollframe, "UIPanelScrollBarTemplate")
local content = CreateFrame("Frame", "content_container", scrollframe)
local deleted_windows = {}
local function clear_content(self)
for i=1, self:GetNumChildren() do
local child = select(i, self:GetChildren())
-- Saving a reference to our previous child frame so that we can reuse it later
if(not tContains(deleted_windows, child)) then
tinsert(deleted_windows, child)
end
child:Hide()
end
end
local function update()
clear_content(content)
local items = 0
local point = -2
local alt_color = false
maxValue = 0
scrollframe.content = nil
for bag=0, NUM_BAG_SLOTS do
for slot=1, GetContainerNumSlots(bag) do
local itemID = GetContainerItemID(bag,slot)
if(itemID) then
local link = GetContainerItemLink(bag,slot)
local name = "frame_"..itemID
local f, tex = nil, nil
local reusing = false
-- attempting to reuse a previous child frame if it exists
-- (which should include the previously created fontstring and button)
if(next(deleted_windows) ~= nil) then
for i=1, #deleted_windows do
if(name == deleted_windows[i]:GetName()) then
f = deleted_windows[i]
reusing = true
end
end
end
-- if not reusing an old frame, create a new one
if(not resuing) then
f = CreateFrame("Frame", "frame_"..itemID, content)
tex = f:CreateTexture(nil, "BACKGROUND")
tex:SetAllPoints()
local t = f:CreateFontString()
t:SetFont("Fonts\\FRIZQT__.TTF", 14, "THIN")
t:SetText(link.." (id: "..itemID..")")
t:SetPoint("TOPLEFT", f, 2, -5)
local b = CreateFrame("Button", "btn_"..itemID, f)
b:SetNormalTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Up")
b:SetPushedTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Down")
b:SetHighlightTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Highlight")
b:SetDisabledTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Disabled")
b:SetSize(32,32)
b:SetPoint("TOPRIGHT", 5,4)
b:SetScript("OnClick",
function(self)
f:Hide()
print(link.." has been removed!")
update()
end
)
f:SetScript("OnEnter",
function(self)
GameTooltip:SetOwner(self, "ANCHOR_LEFT")
GameTooltip:SetItemByID(itemID)
GameTooltip:Show()
end
)
f:SetScript("OnLeave",
function(self)
GameTooltip:SetOwner(UIParent, "ANCHOR_NONE")
GameTooltip:Hide()
end
)
end
-- even if we are reusing, it may not be in the same order
f:SetSize(scrollframe:GetWidth(), 24)
f:ClearAllPoints()
f:SetPoint("TOPLEFT", content, 0, point)
-- also may not have the same colour
if(alt_color) then
tex:SetColorTexture(1, 1, 1, 0.0)
alt_color = false
else
tex:SetColorTexture(1, 1, 1, 0.05)
alt_color = true
end
items = items+1
point = point - (f:GetHeight()+spacing)
maxValue = maxValue + (f:GetHeight()+spacing)
f:Show() -- forcing a show since if we are reusing, the old child was previously hidden
end
end
end
--print("DEBUG: Items: "..items)
--print("DEBUG: maxValue = "..maxValue)
content:SetSize(scrollframe:GetWidth(), scrollframe:GetHeight())
scrollbar:SetMinMaxValues(0, (maxValue-scrollframe:GetHeight()))
scrollframe.content = content
scrollframe:SetScrollChild(content)
end
local function UpdateScrollValue(self, delta)
if(delta == 1 and scrollbar:GetValue() >= 0) then
if(scrollbar:GetValue()-step < 0) then
scrollbar:SetValue(0)
else scrollbar:SetValue(scrollbar:GetValue() - step) end
elseif(delta == -1 and scrollbar:GetValue() < maxValue) then
if(scrollbar:GetValue()+step > maxValue) then
scrollbar:SetValue(maxValue)
else scrollbar:SetValue(scrollbar:GetValue() + step) end
end
end
--parent frame
frame:SetSize(400, 225)
frame:SetPoint("TOPLEFT", 25, -25)
frame:EnableMouse(true)
frame:EnableMouseWheel(true)
frame:SetMovable(true)
frame:SetBackdrop(GameTooltip:GetBackdrop())
frame:SetBackdropColor(GameTooltip:GetBackdropColor())
frame:RegisterForDrag("LeftButton")
local l = frame:CreateLine()
l:SetColorTexture(1,1,1,0.5)
l:SetThickness(1)
l:SetStartPoint("TOPLEFT",10,-30)
l:SetEndPoint("TOPRIGHT",-10,-30)
local header = frame:CreateFontString()
header:SetFont("Fonts\\FRIZQT__.TTF", 16) -- Fonts\\ARIALN.TTF - Fonts\\SKURRI.TTF - -
header:SetText("Scroll List Template")
header:SetPoint("TOPLEFT", frame, 10, -10)
local close_button = CreateFrame("Button", nil, frame, "UIPanelCloseButton")
close_button:ClearAllPoints()
close_button:SetPoint("TOPRIGHT", 0, -1)
local load_button = CreateFrame("Button", "reload", frame, "UIPanelButtonTemplate")
load_button:ClearAllPoints()
load_button:SetPoint("TOPRIGHT", -30, -6)
load_button:SetSize(75,20)
reloadText:SetFont("Fonts\\ARIALN.TTF", 12, nil)
reloadText:SetTextColor(1.0,1.0,0.0,0.8)
reloadText:SetText("Reload list")
scrollframe:SetPoint("TOPLEFT", 10, -35)
scrollframe:SetPoint("BOTTOMRIGHT", -25, 8)
scrollbar:SetPoint("TOPLEFT", frame, "TOPRIGHT", -22, -53)
scrollbar:SetPoint("BOTTOMLEFT", frame, "BOTTOMRIGHT", 22, 22)
scrollbar:SetMinMaxValues(0,0)
scrollbar:SetWidth(16)
scrollbar:SetValue(0)
scrollbar:SetValueStep(step)
scrollbar.scrollStep = step
scrollbar:SetScript("OnValueChanged",
function (self, value)
self:GetParent():SetVerticalScroll(value)
end
)
-- re/load content
update()
frame.scrollframe = scrollframe
frame.scrollbar = scrollbar
frame:SetScript("OnMouseWheel", UpdateScrollValue)
frame:SetScript("OnDragStart", function(self) self:StartMoving() end)
frame:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end)
load_button:SetScript("OnClick", function(self) update() end)
frame:Show()
|