Thread Tools Display Modes
08-15-24, 08:55 PM   #1
Sweetsour
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Dec 2014
Posts: 136
[SOLVED] Need Help with Scrollbar

I have a frame that is populated with a list of buttons that uses a scrollbar to scroll the contents. I've gotten most of the code to work but the one thing I'm getting tripped up on is the contents of the frame update in the way that more list items are added.

The list get populated correctly, however each time a change occurs, it doesn't append the latest list item to the bottom of the list. Instead it adds all the previous items as well causing a massive overlapping of list items.

Frame Contents with Scroll Bar
Lua Code:
  1. frame_main.body = CreateFrame("Frame","FrameBody",frame_main,"BackdropTemplate")
  2. frame_main.body:SetSize(670,352)
  3. frame_main.body:SetPoint("TOPLEFT",frame_main,"TOPLEFT",15,-60)
  4. frame_main.body:SetBackdrop(BACKDROP_DARK_DIALOG_32_32)
  5. frame_main.body:SetFrameStrata("MEDIUM")
  6. frame_main.body:EnableMouse(true)
  7.  
  8. frame_main.body.ScrollBox = CreateFrame("Frame", "FrameBodyScrollBox", frame_main.body, "WowScrollBoxList")
  9. frame_main.body.ScrollBox:SetPoint("TOPLEFT", frame_main.body, "TOPLEFT",4,-5)
  10. frame_main.body.ScrollBox:SetPoint("BOTTOMRIGHT", frame_main.body, "BOTTOMRIGHT",-4,0)
  11.  
  12. frame_main.body.ScrollBar = CreateFrame("EventFrame", "FrameBodyScrollBar", frame_main.body, "MinimalScrollBar")
  13. frame_main.body.ScrollBar:SetPoint("TOPLEFT", frame_main.body, "TOPRIGHT",-24,-15)
  14. frame_main.body.ScrollBar:SetPoint("BOTTOMLEFT", frame_main.body, "BOTTOMRIGHT",0,11)
  15.  
  16. frame_main.body.ScrollView = CreateScrollBoxListLinearView(7,7,7,7,0)
  17. frame_main.body.ScrollView:SetElementExtent(30)
  18. frame_main.body.ScrollView.builder = function(button,data)
  19.     button.id = "FrameItem"..data.info.buttonID
  20.  
  21.     button:SetWidth(656)
  22.     button:RegisterForClicks( "LeftButtonUp" )
  23.     button:SetScript("OnClick",function(self,button,down)
  24.         -- Do things...
  25.     end)
  26.  
  27.     button.info = CreateFrame("Frame",button.id.."Info",button)
  28.     button.info:SetAllPoints(button)
  29.    
  30.     if (data.info.buttonID == 1) then
  31.         button:SetPoint("TOPLEFT",frame_main.body:GetName(),"TOPLEFT",11,-11)
  32.     else
  33.         button:SetPoint("TOP","FrameItem"..(data.info.buttonID-1).."Info","BOTTOM")
  34.     end
  35.  
  36.     if (data.info.buttonID % 2 ~= 0) then
  37.         button.texture = button.info:CreateTexture(button.id.."Texture")
  38.         button.texture:SetAllPoints()
  39.         button.texture:SetColorTexture(0.2,0.2,0.2,0.5)
  40.     end
  41.  
  42.     button:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
  43.  
  44.     button.name = button.info:CreateFontString(button.info:GetName().."Name")
  45.     button.name:SetSize(200,12)
  46.     button.name:SetFont("Fonts\\FRIZQT__.TTF", 10)
  47.     button.name:SetPoint("TOPLEFT",button.info,"TOPLEFT",10,-2)
  48.     button.name:SetJustifyH("LEFT")
  49.     button.name:SetText(data.info.name)
  50.  
  51.     button.time = button.info:CreateFontString(button.info:GetName().."Time")
  52.     button.time:SetSize(200,12)
  53.     button.time:SetFont("Fonts\\FRIZQT__.TTF", 10)
  54.     button.time:SetPoint("TOPLEFT",button.name,"BOTTOMLEFT",0,0)
  55.     button.time:SetJustifyH("LEFT")
  56.     button.time:SetText(data.info.time)
  57. end
  58.  
  59. ScrollUtil.InitScrollBoxListWithScrollBar(frame_main.body.ScrollBox, frame_main.body.ScrollBar, frame_main.body.ScrollView)
  60.  
  61. frame_main.body.ScrollView:SetElementFactory(function(factory,data)
  62.  
  63.     factory("Button", function(button,data)
  64.         frame_main.body.ScrollView.builder(button,data)
  65.     end)
  66. end)

Frame Content Updater
Lua Code:
  1. local detailsData = {}
  2.        
  3. if (_G["MainFrame"].body.ScrollBox.view.dataProvider) then
  4.     detailsData = _G["MainFrame"].body.ScrollBox:GetDataProvider().collection
  5. end
  6.  
  7. local currentIndex = ET_CurrentIndex
  8.  
  9. for index = ET_CurrentIndex, #NameDetails do
  10.     currentIndex = index+1
  11.  
  12.     local name, time = unpack( NameDetails[index] );
  13.  
  14.     local newData = {
  15.         info = {
  16.             name = C_YELLOW..name..C_CLOSE,
  17.             time = date( "%Y-%m-%d %H:%M:%S", time ),
  18.             buttonID = index
  19.         }
  20.     }
  21.  
  22.     tinsert(detailsData,newData)
  23. end;
  24.  
  25. ET_CurrentIndex = currentIndex
  26.  
  27. _G["MainFrame"].body.ScrollBox:SetDataProvider(CreateDataProvider(detailsData))

Last edited by Sweetsour : 08-16-24 at 10:57 PM.
  Reply With Quote
08-15-24, 09:49 PM   #2
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,974
We don't have all the code so it's a bit hard to know.

Lua Code:
  1. local currentIndex = ET_CurrentIndex
eg. Have you tested if ET_CurrentIndex isn't being reset somewhere before "adding" the new data?
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
08-16-24, 09:49 AM   #3
Sweetsour
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Dec 2014
Posts: 136
ET_CurrentIndex is only used within the code that I've shown

I'm just curious if my code for the scrollbar setup is correct. The documentation for it is fairly limited. I found the write up for it on warcraft.wiki.gg but it didn't have anything on adding more elements to the list. I looked for hours for possible examples across different addons and Blizzard code and this is what I've come up with it. I'm so close, haha. Hopefully it's not one of those times where it can't be done

One idea I had but not sure if it's possible is removing the existing elements from the list when running the "update" code I listed?

Last edited by Sweetsour : 08-16-24 at 10:45 AM.
  Reply With Quote
08-16-24, 12:04 PM   #4
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,974
So the first time you do

Code:
local currentIndex = ET_CurrentIndex
ET_CurrentIndex is nil?
which means
Code:
for index = ET_CurrentIndex, #NameDetails do
would error.

I dummied this up from what I could of your code creating/setting the data providor once and then using /tst to add random elements to the list
Lua Code:
  1. local frame_main = CreateFrame("Frame","MainFrame",UIParent)
  2. frame_main:SetSize(5, 5)
  3. frame_main:SetPoint("TOP", -150, 0)
  4.  
  5. frame_main.body = CreateFrame("Frame","FrameBody",frame_main,"BackdropTemplate")
  6. frame_main.body:SetSize(670,352)
  7. frame_main.body:SetPoint("TOPLEFT",frame_main,"TOPLEFT",15,-60)
  8. frame_main.body:SetBackdrop(BACKDROP_DARK_DIALOG_32_32)
  9. frame_main.body:SetFrameStrata("MEDIUM")
  10. frame_main.body:EnableMouse(true)
  11.  
  12. frame_main.body.ScrollBox = CreateFrame("Frame", "FrameBodyScrollBox", frame_main.body, "WowScrollBoxList")
  13. frame_main.body.ScrollBox:SetPoint("TOPLEFT", frame_main.body, "TOPLEFT",4,-5)
  14. frame_main.body.ScrollBox:SetPoint("BOTTOMRIGHT", frame_main.body, "BOTTOMRIGHT",-4,0)
  15.  
  16. frame_main.body.ScrollBar = CreateFrame("EventFrame", "FrameBodyScrollBar", frame_main.body, "MinimalScrollBar")
  17. frame_main.body.ScrollBar:SetPoint("TOPLEFT", frame_main.body, "TOPRIGHT",-24,-15)
  18. frame_main.body.ScrollBar:SetPoint("BOTTOMLEFT", frame_main.body, "BOTTOMRIGHT",0,11)
  19.  
  20. frame_main.body.ScrollView = CreateScrollBoxListLinearView(7,7,7,7,0)
  21. frame_main.body.ScrollView:SetElementExtent(30)
  22. frame_main.body.ScrollView.builder = function(button,data)
  23.     button.id = "FrameItem"..data.info.buttonID
  24.  
  25.     button:SetWidth(656)
  26.     button:RegisterForClicks( "LeftButtonUp" )
  27.     button:SetScript("OnClick",function(self,button,down)
  28.         -- Do things...
  29.     end)
  30.  
  31.     button.info = CreateFrame("Frame",button.id.."Info",button)
  32.     button.info:SetAllPoints(button)
  33.    
  34.     if (data.info.buttonID == 1) then
  35.         button:SetPoint("TOPLEFT",frame_main.body:GetName(),"TOPLEFT",11,-11)
  36.     else
  37.         button:SetPoint("TOP","FrameItem"..(data.info.buttonID-1).."Info","BOTTOM")
  38.     end
  39.  
  40.     if (data.info.buttonID % 2 ~= 0) then
  41.         button.texture = button.info:CreateTexture(button.id.."Texture")
  42.         button.texture:SetAllPoints()
  43.         button.texture:SetColorTexture(0.2,0.2,0.2,0.5)
  44.     end
  45.  
  46.     button:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
  47.  
  48.     button.name = button.info:CreateFontString(button.info:GetName().."Name")
  49.     button.name:SetSize(200,12)
  50.     button.name:SetFont("Fonts\\FRIZQT__.TTF", 10)
  51.     button.name:SetPoint("TOPLEFT",button.info,"TOPLEFT",10,-2)
  52.     button.name:SetJustifyH("LEFT")
  53.     button.name:SetText(data.info.name)
  54.  
  55.     button.time = button.info:CreateFontString(button.info:GetName().."Time")
  56.     button.time:SetSize(200,12)
  57.     button.time:SetFont("Fonts\\FRIZQT__.TTF", 10)
  58.     button.time:SetPoint("TOPLEFT",button.name,"BOTTOMLEFT",0,0)
  59.     button.time:SetJustifyH("LEFT")
  60.     button.time:SetText(data.info.time)
  61. end
  62.  
  63. ScrollUtil.InitScrollBoxListWithScrollBar(frame_main.body.ScrollBox, frame_main.body.ScrollBar, frame_main.body.ScrollView)
  64.  
  65. frame_main.body.ScrollView:SetElementFactory(function(factory,data)
  66.  
  67.     factory("Button", function(button,data)
  68.         frame_main.body.ScrollView.builder(button,data)
  69.     end)
  70. end)
  71.  
  72.  
  73.  
  74. frame_main.body.Data = CreateDataProvider() -- create/set the data providoer once
  75. frame_main.body.ScrollBox:SetDataProvider(frame_main.body.Data)
  76.  
  77. local NameDetails = {} -- dummy data
  78. for i=1, 5 do
  79.     tinsert(NameDetails, { "Name"..i, GetTime()})
  80. end
  81.  
  82. local function AppendName(index) -- function to add new lines
  83.     local name, time = unpack( NameDetails[index] );
  84.     local newData = {
  85.     info = {
  86.             name = name,
  87.             time = date( "%Y-%m-%d %H:%M:%S", time ),
  88.             buttonID = index
  89.         }
  90.     }
  91.     frame_main.body.Data:Insert(newData)
  92. end
  93.  
  94. --Initialise the scrollbox
  95. local ET_CurrentIndex = #NameDetails
  96. for index=1, ET_CurrentIndex do
  97.     AppendName(index)
  98. end
  99.  
  100. frame_main.body.ScrollBox:ScrollToBegin(ScrollBoxConstants.NoScrollInterpolation)
  101.  
  102. -- dummy slashcommand to add random extra entries
  103. SLASH_TESTMENU1 = "/tst"
  104. SlashCmdList.TESTMENU = function(msg)
  105.     local total = #NameDetails
  106.     local add = random(1, 4)
  107.     for i=1, add do -- add entries to the "source" table for realism
  108.         tinsert(NameDetails, { "Name"..total+i, GetTime()})
  109.     end
  110.     for i= ET_CurrentIndex+1, #NameDetails do -- insert added entries into the data provider
  111.         AppendName(i)
  112.     end
  113.     ET_CurrentIndex = #NameDetails
  114.     frame_main.body.ScrollBox:ScrollToEnd(ScrollBoxConstants.NoScrollInterpolation)
  115. end

If you wanted to completely reload the list data you could
Code:
frame_main.body.Data:Flush()
and then AppendName() all the entires in the NameDetails table and scroll to the top/end/whatever
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 08-16-24 at 01:19 PM.
  Reply With Quote
08-16-24, 08:09 PM   #5
Sweetsour
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Dec 2014
Posts: 136
That certainly did the trick! I guess it makes sense after the fact that the reason the issue was happening was because I was adding a new data provider every time, haha. Thanks for taking the time to whip that up!

Though, I seem to be having a new issue. While all the buttons are populating nicely in the list, scrolling sends the whole thing into chaos, lol. By this I mean, every scroll increment, new buttons are added but more of the overlapping is happening. In the first chunk of code you sent me, I put a print statement on line #23, inside the button builder and the print statement was firing every scroll increment. Is that normal behavior?
  Reply With Quote
08-16-24, 08:15 PM   #6
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,974
What buttons?

It sounds like you're creating new buttons every scroll instead of testing if the button has been added to the row already before creating/adding.

You don't get a new row for every entry in the data table, the scroll creates enough rows to fill the viewable area and then re-uses (refills) them when you scroll.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
08-16-24, 08:37 PM   #7
Sweetsour
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Dec 2014
Posts: 136
I wasn't sure if it was something that I did wrong when looking at the code you provided. I threw your code into a new lua file and ran it and it seems to be running into the same issue when scrolling occurs.

It's strange. Here's some screenshots to help illustrate what's going on.


  Reply With Quote
08-16-24, 09:02 PM   #8
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,974
I wasn't really looking at that.

Change
Code:
frame_main.body.ScrollView.builder = function(button,data)
    -- ...
end
to:
Lua Code:
  1. frame_main.body.ScrollView.builder = function(button,data)
  2.     if not button.info then -- setup the row if it hasn't alread been done
  3.         button.id = "FrameItem"..data.info.buttonID
  4.  
  5.         button:SetWidth(656)
  6.         button:RegisterForClicks( "LeftButtonUp" )
  7.         button:SetScript("OnClick",function(self,button,down)
  8.         -- Do things...
  9.         end)
  10.  
  11.         button.info = CreateFrame("Frame",button.id.."Info",button)
  12.         button.info:SetAllPoints(button)
  13.    
  14.         if (data.info.buttonID == 1) then
  15.             button:SetPoint("TOPLEFT",frame_main.body:GetName(),"TOPLEFT",11,-11)
  16.         else
  17.             button:SetPoint("TOP","FrameItem"..(data.info.buttonID-1).."Info","BOTTOM")
  18.         end
  19.         button.texture = button:CreateTexture(button.id.."Texture")
  20.         button.texture:SetAllPoints()
  21.  
  22.         button:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
  23.  
  24.         button.name = button.info:CreateFontString(button.info:GetName().."Name")
  25.         button.name:SetSize(200,12)
  26.         button.name:SetFont("Fonts\\FRIZQT__.TTF", 10)
  27.         button.name:SetPoint("TOPLEFT",button.info,"TOPLEFT",10,-2)
  28.         button.name:SetJustifyH("LEFT")
  29.  
  30.         button.time = button.info:CreateFontString(button.info:GetName().."Time")
  31.         button.time:SetSize(200,12)
  32.         button.time:SetFont("Fonts\\FRIZQT__.TTF", 10)
  33.         button.time:SetPoint("TOPLEFT",button.name,"BOTTOMLEFT",0,0)
  34.         button.time:SetJustifyH("LEFT")
  35.     end
  36.     -- update the row background (greenbar)
  37.     if (data.info.buttonID % 2 ~= 0) then
  38.             button.texture:SetColorTexture(0.2,0.2,0.2,0.5)
  39.     else
  40.             button.texture:SetColorTexture(0,0,0,1)
  41.     end
  42.     -- display the name/time text for the row
  43.     button.name:SetText(data.info.name)
  44.     button.time:SetText(data.info.time)
  45. end

I create button.texture on the button instead of button.info to save messing around with the draw layers.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 08-16-24 at 10:31 PM.
  Reply With Quote
08-16-24, 10:56 PM   #9
Sweetsour
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Dec 2014
Posts: 136
Spectacular, that did it!

One last issue that persisted was the button textures would lose their alternating pattern when scrolling. The fix I found for this was using button:GetOrderIndex() instead of button.id when setting the texture color

Thanks a ton for your help!
  Reply With Quote

WoWInterface » AddOns, Compilations, Macros » AddOn Help/Support » Need Help with Scrollbar


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