Thread Tools Display Modes
08-24-19, 10:34 AM   #1
Auz
A Defias Bandit
 
Auz's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2013
Posts: 3
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()

Last edited by Auz : 08-25-19 at 08:58 AM. Reason: Update
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » Updating SCrollFrame content without reloading the UI

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off