Thread Tools Display Modes
10-13-21, 07:08 PM   #1
Khazak
A Murloc Raider
 
Khazak's Avatar
Join Date: Oct 2021
Posts: 4
How to show and hide frames

I am having difficulty with frames not properly showing and hiding.

Addon behavior can be seen here .

The intended behavior is to have the list show a list of user defined spells based on category. The list itself is populated properly, debug prints are all as expected.

The issue I'm having is with reusing each line. As I understand it, you can't delete frames. Only hide them. My idea is to then hide all the frames representing each line in the spell list, replace the text as needed with the new list, and then show the ones that got updated. This does not seem to be working. The first line overlays the new spell id text on top of the old, and none of the others get updated.
  • Is there a better way to change lists? Is there a way I can throw out the old list and make new frames for each list?
  • Why is Hide() not actually hiding the frames? The call goes through without error, and if I use /fstack I can manually hide the frame using its id. Do I need to do something to refresh the parent frame?

Code is here.

The debug prints are showing expected results, selecting a new list prints the right number of "hiding" and "setting existing row" messages, just none of the rows change except the first. If anything isn't clear I am happy to explain in more detail.

Last edited by Khazak : 10-13-21 at 07:12 PM.
  Reply With Quote
10-14-21, 12:00 PM   #2
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
You don't create new rows in the list, you create the number of rows you want to display and then re-use them with information from your source table as you scroll through it. If you want to change the table of information you want to display, you re-initialise the list using the other table.

A really quick and dirty example using 3 source tables.
The list only display 3 rows and each table has only 4 entries (so not much scrolling).
You can switch from one source table to another using /kl taunt, /kl hit, /kl stuff

Lua Code:
  1. local initList = "taunt"
  2.  
  3. local sections = {
  4.     taunt = 1,
  5.     hit = 2,
  6.     stuff = 3,
  7. }
  8. local listEntries = {
  9.     [1]={
  10.         {text="123", value=1 },
  11.         {text="456", value=4 },
  12.         {text="789", value=7 },
  13.         {text="000", value=0 },
  14.     },
  15.     [2]={
  16.         {text="ABC", value=1 },
  17.         {text="DEF", value=2 },
  18.         {text="GHI", value=3 },
  19.         {text="JKL", value=4 },
  20.     },
  21.     [3]={
  22.         {text="MNO", value=5 },
  23.         {text="PWR", value=6 },
  24.         {text="STU", value=8 },
  25.         {text="VWX", value=9 },
  26.     },
  27. }
  28.  
  29. local function UpdateList(self, id, init) -- the work of re-using the rows (buttons and texts) happens here
  30.     local table = listEntries[sections[id]]
  31.     if not table then return end
  32.     local numOptions = #table
  33.     if init then
  34.         self.offset = 0
  35.     end
  36.     local offset = self.offset or 0
  37.     local index, button
  38.     local entries = #self.rows
  39.     local current = 0
  40.     for i=1, #table do
  41.         index = offset + i
  42.         if table[index] then
  43.             current = current + 1
  44.             button = self.rows[current]
  45.             button:Show()
  46.             button.index = index
  47.             button.value = table[index].value
  48.             button.Text:SetText(table[index].text.." [value="..table[index].value.."]")
  49.             if current == entries then break end -- only loop enough to full #buttons
  50.         end
  51.     end
  52.     if current < entries then
  53.         for i = current + 1, entries do
  54.             self.rows[i]:Hide()
  55.         end
  56.     end
  57.     FauxScrollFrame_Update(self, numOptions, entries, self.rows[1]:GetHeight())
  58. end
  59.  
  60. local function OnClick(self) -- Use the index set during UpdateList along with the curent source table (initList)
  61.     print("Clicked", listEntries[sections[initList]][self.index].value, listEntries[sections[initList]][self.index].text)
  62. end
  63.  
  64. local f = CreateFrame("ScrollFrame", "KhazakList", UIParent, "FauxScrollFrameTemplate")
  65. f:SetSize(100, 60)
  66. f:SetPoint("TOPLEFT", 5, -5)
  67. f.rows = {}
  68. for i=1, 3 do -- create a fixed no. of rows to display (3)
  69.     local r = CreateFrame("Button", "$parentRow"..i, f)
  70.     tinsert(f.rows, r)
  71.     r:SetSize(f:GetWidth(), f:GetHeight()/3) -- The height of a row determines the relative offset the scroll bar uses (1/3 the list height here)
  72.     if i == 1 then
  73.         r:SetPoint("TOPLEFT")
  74.     else
  75.         r:SetPoint("TOP", f.rows[i-1], "BOTTOM")
  76.     end
  77.     f.Texture = f:CreateTexture()
  78.     f.Texture:SetAllPoints()
  79.     f.Texture:SetTexture("Interface/BUTTONS/WHITE8X8")
  80.     f.Texture:SetVertexColor(0.2, 0.2, 0.2, 0.5)
  81.     r.Text = r:CreateFontString()
  82.     r.Text:SetFontObject(GameFontNormal)
  83.     r.Text:SetPoint("LEFT", 4, 0)
  84.     r:SetScript("OnClick", OnClick)
  85. end
  86.  
  87. f:SetScript("OnVerticalScroll", function(self, offset) -- When the scroll thumb moves, save the new offset and update from the current table
  88.     self.ScrollBar:SetValue(offset)
  89.     self.offset = math.floor(offset / self.rows[1]:GetHeight())
  90.     UpdateList(self, initList)
  91.  
  92. end)
  93.  
  94. UpdateList(f, initList, true) -- first time initalisation of the list.
  95.  
  96. _G["SLASH_KhazakList1"] = "/kl"
  97. SlashCmdList.KhazakList = function(msg)
  98.     msg = strlower(msg)
  99.     if not sections[msg] then
  100.         print(msg, "not found in sections!")
  101.         return
  102.     end
  103.     initList = msg
  104.     UpdateList(f, initList, true) -- Initialise the list using the newly selected table
  105. end
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 10-14-21 at 03:08 PM.
  Reply With Quote
10-14-21, 05:54 PM   #3
Khazak
A Murloc Raider
 
Khazak's Avatar
Join Date: Oct 2021
Posts: 4
Originally Posted by Fizzlemizz View Post
You don't create new rows in the list, you create the number of rows you want to display and then re-use them with information from your source table as you scroll through it.
Right, I got that and think I'm doing that.

My issue is that updates to the existing rows are not taking effect. I get the prints here for hiding existing frames, setting the new string, and then showing the updates frame. But, the content of the frame does not change on screen. I will have to check your example closely to see if there's a weird parenting issue or something because I'm following the same approach I think.

Lua Code:
  1. local function CreateSpellList()
  2.     for key, value in pairs(row) do
  3.         ADDON.Print("Hiding")
  4.         value:ClearSpell()
  5.     end
  6.  
  7.     row[1] = ADDON.SpellRow:CreateRow(listScrollFrame, 1, 1)
  8.     row[1]:GetFrame():SetPoint('TOPLEFT', 'AAOptionsFrame', 'TOPLEFT', 25, -10)
  9.     local currentRow = 1
  10.     for spellId, _ in pairs(AstralAnalytics.spellIds[currentDropdownValue]) do
  11.         if row[currentRow] == nil then
  12.             ADDON.Print('new row for ' .. currentRow .. ' with id ' .. spellId)
  13.             row[currentRow] = ADDON.SpellRow:CreateRow(listScrollFrame, currentRow, spellId)
  14.             row[currentRow]:GetFrame():SetPoint('TOPLEFT', 'spellIdRow' .. currentRow-1, 'BOTTOMLEFT', 0, 0)
  15.         else
  16.             ADDON.Print('setting existing row for ' .. currentRow .. ' with id ' .. spellId)
  17.             row[currentRow]:SetSpell(spellId)
  18.             row[currentRow]:GetFrame():Show()
  19.         end
  20.         currentRow = currentRow + 1
  21.     end
  22.     ADDON.Print(table.getn(row))
  23. end
  Reply With Quote
10-14-21, 07:04 PM   #4
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
Originally Posted by Khazak View Post
Right, I got that and think I'm doing that.
Not really.

Your code is trying to ADDON.SpellRow:CreateRow(..) for every entry in your source table. When you switch to a different source table you ADDON.SpellRow:CreateRow(..) for any entries over and above the number in the previous table. It also creates a new row[1] each time even if it already exists which I suspect is causing the overlap.

In reality, when you create the list, you decide the max. no. of rows you want to see on-screen and create that many only. If you have 3 tables wih 20, 50 and 100 entries but you only want to see 10 rows at a time, create 10 rows.

You will just keep re-using those exact same row buttons no matter which table is selected or how many entries they might have. The OnVerticalScroll script tells your code which offset (entry number in the source table) to start filling your 10 rows with every time the user scrolls.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 10-14-21 at 08:48 PM.
  Reply With Quote
10-15-21, 07:41 AM   #5
Khazak
A Murloc Raider
 
Khazak's Avatar
Join Date: Oct 2021
Posts: 4
Okay, so I can make the change to just create a bunch of rows upfront instead of creating more on the fly. My frame will show 30+ rows at a time and right now I only have 17 rows in my longest test list.

This does not address my confusion about why editing the existing rows is not working. On lines 3-4, I set the text on each row to an empty string and then hide the frame. Later on lines 16-18, I re use the same rows and set a new string on them and tell them to show. The code executes without error, but there is no change. If I have a list of 17 and then switch to a list of 8, I should see the bottom 9 rows hide.

I thought maybe I needed to call FauxScrollFrame_Update to get the frame to refresh based on your example but that does not seem to fix it.
  Reply With Quote
10-15-21, 08:59 AM   #6
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
When you call ADDON.SpellRow:CreateRow(parent, index, spell) the self inside that function refers to the ADDON.SpellRow table. You're saving each new row as ADDON.SpellRow.frame and overwriting the previous reference. Then funtion returns ADDON.SpellRow (self).

ie.
row[1] will = ADDON.SpellRow
row[2] will = ADDON.SpellRow
row[3] will = ADDON.SpellRow
...

and ADDON.SpellRow.frame will always contain the last row created.

The functions should look a bit more like the following so they can identify which row they should act on.
Lua Code:
  1. function ADDON.SpellRow:CreateRow(parent, index, spell)
  2.   -- create a distinct new local reference to a new frame each time  
  3.     local frame = CreateFrame('BUTTON', 'spellIdRow' .. index, parent)
  4.     frame:SetSize(ADDON:Scale(290), ADDON:Scale(16))
  5.  
  6.     frame.background = frame:CreateTexture(nil, 'BACKGROUND')
  7.     frame.background:SetAllPoints(frame)
  8.     frame.background:SetTexture([[Interface\AddOns\AstralAnalytics\Media\Texture\Flat.tga]])
  9.     frame.background:SetAlpha(.6)
  10.     frame.background:Show()
  11.  
  12.     frame.name = frame:CreateFontString(nil, 'OVERLAY', 'GameFontNormal')
  13.     frame.name:SetPoint('LEFT', frame, 'LEFT', 4, -1)
  14.     frame.name:SetTextColor(1, 1, 1)
  15.     ADDON.SpellRow:SetSpell(frame, spell)
  16.     return frame
  17. end
  18.  
  19. function ADDON.SpellRow:SetSpell(self, spell)
  20.     local name, rank, icon = GetSpellInfo(spell)
  21.     self.name:SetText(name .. " (" .. spell .. ")")
  22.     self:Show()
  23. end
  24.  
  25. function ADDON.SpellRow:ClearSpell(self)
  26.     self.name:SetText('')
  27.     self:Hide()
  28. end
  29.  
  30. local function CreateSpellList()
  31.     for key, value in pairs(row) do
  32.         ADDON.Print("Hiding")
  33.         ADDON.SpellRow:ClearSpell(value)
  34.     end
  35.  
  36.     row[1] = ADDON.SpellRow:CreateRow(listScrollFrame, 1, 1)
  37.     row[1]:SetPoint('TOPLEFT', parentListContainer, 'TOPLEFT', 25, -10)
  38.     local currentRow = 1
  39.     for spellId, _ in pairs(AstralAnalytics.spellIds[currentDropdownValue]) do
  40.         if row[currentRow] == nil then
  41.             ADDON.Print('new row for ' .. currentRow .. ' with id ' .. spellId)
  42.             row[currentRow] = ADDON.SpellRow:CreateRow(listScrollFrame, currentRow, spellId)
  43.             row[currentRow]:SetPoint('TOPLEFT', 'spellIdRow' .. currentRow-1, 'BOTTOMLEFT', 0, 0)
  44.         else
  45.             print('setting existing row for ' .. currentRow .. ' with id ' .. spellId)
  46.             ADDON.SpellRow:SetSpell(row[currentRow], spellId)
  47.             row[currentRow]:Show()
  48.         end
  49.         currentRow = currentRow + 1
  50.     end
  51.     ADDON.Print(table.getn(row))
  52. end

I didn't change all the code because the CreateSpellList() shouldn't work this way (continually replacing the entries in row[] and losing the old ones) so this is not really a fix, just an explanation as to why you weren't seeing the rows refresh as you expected.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 10-15-21 at 10:04 AM.
  Reply With Quote
10-15-21, 12:28 PM   #7
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
I updated my original code so the each time you /kl ... it adds 5 extra entries to the selected source table before initialising. It shows that extra source entries just means more scrolling to get to the top/bottom of your source table, not more rows added to the displayed list.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
10-20-21, 08:52 PM   #8
Khazak
A Murloc Raider
 
Khazak's Avatar
Join Date: Oct 2021
Posts: 4
Returning just the frame fixed it. Still plenty of work left on this list, but the issue from the gif was resolved by only returning the created frame.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » How to show and hide frames

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