Thread Tools Display Modes
04-28-23, 06:46 AM   #1
AeroMaxxD
An Aku'mai Servant
Join Date: Dec 2022
Posts: 33
Adding a ScrollFrame to a CharacterFrame tab

So I am trying to write my first addon, it would just list a table of results 2 columns on the tab.

My initial idea was to have next and previous buttons to look through the results.

But I have since discovered there is a scroll frame, so was wanting to use a scroll frame instead.

The table itself will have 1 row added to the results for each day that the character was logged into.

A scroll frame should be ok right if it had a lot of data, as in a year or more?

Lua Code:
  1. local TabName="AMD";
  2. local TabID=CharacterFrame.numTabs+1;
  3. local Tab=CreateFrame("Button", "$parentTab"..TabID, CharacterFrame, "CharacterFrameTabTemplate", TabID);
  4. PanelTemplates_SetNumTabs(CharacterFrame, TabID);
  5. Tab:SetPoint("LEFT", "$parentTab"..(TabID-1), "RIGHT", -16, 0);
  6. Tab:SetText(TabName);
  7. -- Tab:SetID(TabID);
  8.  
  9. tinsert(CHARACTERFRAME_SUBFRAMES, "AMD_TabOnCharacterFrame");
  10.  
  11. hooksecurefunc("CharacterFrameTab_OnClick", function(self, button)
  12.     if self:GetID() == TabID then
  13.         ToggleCharacter("AMD_TabOnCharacterFrame")
  14.     end
  15. end)

Code:
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ http://wowprogramming.com/FrameXML/UI.xsd">
	<Frame name="AMD_TabOnCharacterFrame" parent="CharacterFrame" frameStrata="HIGH" enableMouse="true" movable="true" setallpoints="true" id="4">
		<Size x="206" y="580"/>
		<Frames>
			<Frame name="$parent_History" parent="AMD_TabOnCharacterFrame">
				<Size x="300" y="325"/>
				<Anchors>
					<Anchor point="CENTER" relativePoint="CENTER" relativeTo="CharacterFrame"/>
				</Anchors>
				<Frames>
					<Frame name="$parent_ScrollFrame" parent="AMD_TabOnCharacterFrame_History" inherits="UIPanelScrollFrameTemplate">
					</Frame>
				</Frames>
				<Layers>
					<Layer level="OVERLAY">
						<FontString name="History_Title" parentKey="History_title" inherits="GameFontNormal">
							<Color r="1" g="1" b="1" a="1"/>
							<Anchors>
								<Anchor point="TOP">
									<Offset x="0" y="20"/>
								</Anchor>
							</Anchors>
						</FontString>
					</Layer>
				</Layers>
			</Frame>
		</Frames>
	</Frame>
</Ui>
This gives me errors and I have no idea what they mean.

Code:
Interface/SharedXML/SecureUIPanelTemplates.lua:64: attempt to call method 'SetVerticalScroll' (a nil value)
Code:
Interface/SharedXML/SecureUIPanelTemplates.xml:120 Frame AMD_TabOnCharacterFrame_History_ScrollFrame: Unknown script element OnScrollRangeChanged
Code:
Interface/SharedXML/SecureUIPanelTemplates.xml:121 Frame AMD_TabOnCharacterFrame_History_ScrollFrame: Unknown script element OnVerticalScroll
  Reply With Quote
04-28-23, 10:38 AM   #2
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,879
Lists are complicated until you understand them.

This is a list example created by someone else and loosly based on what I know of your addon.

The AppendListItem function is actually creating the the information table that is displayed in the list.

XML
XML Code:
  1. <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ http://wowprogramming.com/FrameXML/UI.xsd">
  2.     <!-- formatting for each row of the list -->
  3.     <Frame name="AMD_ScrollableListItemTemplate" mixin="AMD_ScrollableListItemMixin" virtual="true">
  4.         <Size y="21"/>
  5.         <Layers>
  6.             <Layer level="BACKGROUND">
  7.                 <Texture parentKey="Background" setAllPoints="true"/>
  8.             </Layer>
  9.             <Layer level="OVERLAY">
  10.                 <FontString parentKey="Text" inherits="GameFontHighlight" setAllPoints="true"/>
  11.             </Layer>
  12.         </Layers>
  13.     </Frame>
  14.  
  15.     <!-- Create a list template extending the Blizzard scrollbox code for customised use -->
  16.     <Frame name="AMD_ScrollableListTemplate" mixin="AMD_ScrollableListMixin" virtual="true">
  17.         <Frames>
  18.             <Frame parentKey="ScrollBox" inherits="WowScrollBoxList"/>
  19.             <EventFrame parentKey="ScrollBar" inherits="WowTrimScrollBar">
  20.                 <Anchors>
  21.                     <Anchor point="TOPRIGHT"/>
  22.                     <Anchor point="BOTTOMRIGHT"/>
  23.                 </Anchors>
  24.             </EventFrame>
  25.         </Frames>
  26.         <Scripts>
  27.             <OnLoad method="OnLoad"/>
  28.         </Scripts>
  29.     </Frame>
  30.  
  31.     <Frame name="AMD_TabOnCharacterFrame" parent="CharacterFrame" mixin="AMD_TabOnCharacterFrameMixin" frameStrata="HIGH" enableMouse="true" movable="true" setallpoints="true" id="4" inherits="ButtonFrameTemplate">
  32.         <Frames>
  33.  
  34.             <!-- add the listbox top you frame -->
  35.             <Frame parentKey="ListFrame" inherits="AMD_ScrollableListTemplate">
  36.                 <Anchors>
  37.                     <Anchor point="TOPLEFT">
  38.                         <Offset><AbsDimension y="-50"/></Offset>
  39.                     </Anchor>
  40.                     <Anchor point="BOTTOMRIGHT">
  41.                         <Offset><AbsDimension y="25"/></Offset>
  42.                     </Anchor>
  43.                 </Anchors>
  44.             </Frame>
  45.  
  46.             <Frame name="$parent_History" parent="AMD_TabOnCharacterFrame">
  47.                 <Anchors>
  48.                     <Anchor point="CENTER" relativePoint="CENTER" relativeTo="CharacterFrame"/>
  49.                 </Anchors>
  50.             </Frame>
  51.             <Button name="$parent_Options" inherits="PanelTopTabButtonTemplate" text="Options">
  52.                 <Anchors>
  53.                     <Anchor point="BOTTOMLEFT" x="98" y="440"/>
  54.                 </Anchors>
  55.                 <ButtonText parentKey="Text">
  56.                     <Size x="0" y="10"/>
  57.                     <Anchors>
  58.                         <Anchor point="CENTER" x="0" y="-8"/>
  59.                     </Anchors>
  60.                 </ButtonText>
  61.             </Button>
  62.             <Button name="$parent_PreviousButton" inherits="UIPanelButtonTemplate" text="NEXT">
  63.                 <Size x="109" y="22"/>
  64.                 <Anchors>
  65.                     <Anchor point="BOTTOMRIGHT" x="-6" y="6"/>
  66.                 </Anchors>
  67.             </Button>
  68.             <Button name="$parent_SaveButton" inherits="UIPanelButtonTemplate" text="BACK">
  69.                 <Size x="100" y="22"/>
  70.                 <Anchors>
  71.                     <Anchor point="BOTTOMLEFT" x="95" y="83"/>
  72.                 </Anchors>
  73.             </Button>
  74.             <Button name="$parent_NextButton" inherits="UIPanelButtonTemplate" text="PREVIOUS">
  75.                 <Size x="109" y="22"/>
  76.                 <Anchors>
  77.                     <Anchor point="BOTTOMLEFT" x="6" y="6"/>
  78.                 </Anchors>
  79.             </Button>
  80.         </Frames>
  81.             <Scripts>
  82.                 <OnLoad method="OnLoad"/>
  83.             </Scripts>
  84.     </Frame>
  85. </Ui>

lua:
Lua Code:
  1. AMD_ScrollableListItemMixin = {} -- does the visual row display as the list is scrolled
  2. function AMD_ScrollableListItemMixin:Init(elementData)
  3.     self.Background:SetColorTexture(elementData.color:GetRGBA())
  4.     self.Text:SetText(elementData.text)
  5. end
  6.  
  7. AMD_TabOnCharacterFrameMixin = {}
  8. function AMD_TabOnCharacterFrameMixin:OnLoad() -- add 100 items to the list to be scrolled
  9.     for _ = 1, 100 do
  10.         self.ListFrame:AppendListItem()
  11.     end
  12. end
  13.  
  14. AMD_ScrollableListMixin = {}
  15. function AMD_ScrollableListMixin:OnLoad() -- initialise the list
  16.     -- The data provider acts as the backing model for a scrollview each
  17.     -- element ("elementData") in the data provider corresponds to one row
  18.     -- in the displayed list. The actual values can be anything. The default
  19.     -- below creates an empty data provider, but you can pass a table in as
  20.     -- the first argument to pre-populate it with values.
  21.  
  22.     self.DataProvider = CreateDataProvider()
  23.  
  24.     -- The scroll view is responsible for managing the acquisition of pooled
  25.     -- frames and laying them out for display. This needs to be supplied with
  26.     -- a data provider, an element extent (size), and an element factory or
  27.     -- initializer at minimum.
  28.     --
  29.     -- The extent must be the actual height of each row. It can be dynamically
  30.     -- calculated with a function, but a fixed extent is much more performant.
  31.  
  32.     local elementExtent = 21
  33.  
  34.     self.ScrollView = CreateScrollBoxListLinearView()
  35.     self.ScrollView:SetDataProvider(self.DataProvider)
  36.     self.ScrollView:SetElementExtent(elementExtent)
  37.  
  38. --[[ -- Currently use on Wrath pre 3.4.1 and Vanilla
  39.     self.ScrollView:SetElementInitializer("Frame", "AMD_ScrollableListItemTemplate", function(frame, elementData)
  40.         -- This is called each time the scrollview acquires a frame this
  41.         -- should generally call a method on the acquired frame and update
  42.         -- its visual state accordingly.
  43.  
  44.         frame:Init(elementData)
  45.     end)
  46.  
  47. ]]--
  48. --[[ Use on Retail and Wrath post 3.4.1 ]]--
  49.     self.ScrollView:SetElementInitializer("AMD_ScrollableListItemTemplate", function(frame, elementData)
  50.         -- This is called each time the scrollview acquires a frame this
  51.         -- should generally call a method on the acquired frame and update
  52.         -- its visual state accordingly.
  53.  
  54.         frame:Init(elementData)
  55.     end)
  56.  
  57.     -- Padding and spacing are optional these are just demo values. The
  58.     -- defaults if no padding is configured will all be zero.
  59.  
  60.     local paddingT = 10
  61.     local paddingB = 10
  62.     local paddingL = 10
  63.     local paddingR = 10
  64.     local spacing = 5
  65.  
  66.     self.ScrollView:SetPadding(paddingT, paddingB, paddingL, paddingR, spacing)
  67.  
  68.     -- The below call is required to hook everything up automatically.
  69.  
  70.     ScrollUtil.InitScrollBoxListWithScrollBar(self.ScrollBox, self.ScrollBar, self.ScrollView)
  71.  
  72.     -- If you want the scrollbar to show or hide automatically based on
  73.     -- whether or not the region can be scrolled, you'll need two anchor
  74.     -- tables to configure the managed scroll visibility behavior.
  75.  
  76.     local anchorsWithBar = {
  77.         CreateAnchor("TOPLEFT", self, "TOPLEFT", 4, -4),
  78.         CreateAnchor("BOTTOMRIGHT", self.ScrollBar, "BOTTOMLEFT", 0, 4),
  79.     }
  80.  
  81.     local anchorsWithoutBar = {
  82.         CreateAnchor("TOPLEFT", self, "TOPLEFT", 4, -4),
  83.         CreateAnchor("BOTTOMRIGHT", self, "BOTTOMRIGHT", -4, 4),
  84.     }
  85.  
  86.     ScrollUtil.AddManagedScrollBarVisibilityBehavior(self.ScrollBox, self.ScrollBar, anchorsWithBar, anchorsWithoutBar)
  87. end
  88.  
  89. function AMD_ScrollableListMixin:AppendListItem() -- this creates the line items
  90.     local color = CreateColor(fastrandom(), fastrandom(), fastrandom())
  91.     local text = string.format("Time: %.5f", GetTime())
  92.  
  93.     local elementData = -- Used by the list to display each list row text and color as they're scrolled
  94.     {
  95.         color = color,
  96.         text = text,
  97.     }
  98.  
  99.     self.DataProvider:Insert(elementData)
  100.     self.ScrollBox:ScrollToEnd(ScrollBoxConstants.NoScrollInterpolation)
  101. end
  102.  
  103. function AMD_ScrollableListMixin:RemoveListItem()
  104.     local lastIndex = self.DataProvider:GetSize()
  105.     self.DataProvider:RemoveIndex(lastIndex)
  106. end
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
04-30-23, 04:42 AM   #3
AeroMaxxD
An Aku'mai Servant
Join Date: Dec 2022
Posts: 33
This is what I use right now to output the list contents to the frame.

I thought I would just use the same code but change the frame that was the output.

Lua Code:
  1. for k = ((15 - (CURRENT_PAGE * 15)) * -1) + 1, END, 1 do
  2.     print( "k", k ); -- For debugging.
  3.  
  4.     offset = offset - 20;
  5.     local dateString = AMD_Content:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall");
  6.     dateString:SetPoint("TOPLEFT", AMD_TabOnCharacterFrame_History, 0, offset);
  7.  
  8.     local day = string.sub(SavesSorted[k], 0, 2);
  9.     local month = string.sub(SavesSorted[k], 3, 4);
  10.     local year = string.sub(SavesSorted[k], 5, 6);
  11.     if (CURRENT_DATE == day .. month .. year) then
  12.         dateString:SetText("Today")
  13.     else
  14.         dateString:SetText(day .. "." .. month .. "." .. year);
  15.     end
  16.     dateString:SetTextColor(1, 1, 1, 1);
  17.  
  18.     print(day, month, year); -- For debugging
  19. done

Last edited by AeroMaxxD : 04-30-23 at 05:19 AM.
  Reply With Quote
04-30-23, 05:25 AM   #4
AeroMaxxD
An Aku'mai Servant
Join Date: Dec 2022
Posts: 33
On another note I also asked about how to add a tab to the character frame on the official Blizzard forums, someone there responded with the code below.

This is what gave me the idea of a scroll frame, initially, I dismissed it however, and was still going to go with the next and previous buttons, I've since changed my mind.

Lua Code:
  1. local TabName = "MyNewTab";
  2.  
  3. local TabID = CharacterFrame.numTabs + 1;
  4. local Tab = CreateFrame("Button", "$parentTab"..TabID, CharacterFrame, "CharacterFrameTabTemplate", TabID);
  5. PanelTemplates_SetNumTabs(CharacterFrame, TabID);
  6. Tab:SetPoint("LEFT", "$parentTab" .. (TabID-1), "RIGHT", -16, 0);
  7. Tab:SetText(TabName);
  8.  
  9. local Panel = CreateFrame("Frame", nil, CharacterFrame);
  10. Panel:SetAllPoints(CharacterFrame);
  11.  
  12. Panel.ScrollBox = CreateFrame("ScrollFrame", nil, Panel, "UIPanelScrollFrameTemplate")
  13. Panel.ScrollBox:SetPoint("TOPLEFT", Panel, "TOPLEFT", 10, -64) --Left / Up
  14. Panel.ScrollBox:SetPoint("BOTTOMRIGHT", Panel, "BOTTOMRIGHT", -30, 10) --Right / Down
  15.  
  16. Panel.Content = CreateFrame("Frame", nil, Panel)
  17. Panel.Content:SetPoint("CENTER", 0, -25)
  18. Panel.Content:SetSize(305, 351) -- Width / Height
  19. Panel.Content.Background = Panel.Content:CreateTexture(nil, "OVERLAY")
  20. Panel.Content.Background:SetColorTexture(math.random(), math.random(), math.random(), 0.2)
  21. Panel.Content.Background:SetAllPoints()
  22.  
  23. Tab:SetScript("OnClick", function(self, arg1)
  24.     PanelTemplates_SetTab(CharacterFrame, TabID)
  25.     if _G["HonorFrame"] ~= nil then
  26.         _G["HonorFrame"]:Hide()
  27.     end
  28.     if _G["PaperDollFrame"] ~= nil then
  29.         _G["PaperDollFrame"]:Hide()
  30.     end
  31.     if _G["PetPaperDollFrame"] ~= nil then
  32.         _G["PetPaperDollFrame"]:Hide()
  33.     end
  34.     if _G["HonorFrame"] ~= nil then
  35.         _G["HonorFrame"]:Hide()
  36.     end
  37.     if _G["SkillFrame"] ~= nil then
  38.         _G["SkillFrame"]:Hide()
  39.     end
  40.     if _G["ReputationFrame"] ~= nil then
  41.         _G["ReputationFrame"]:Hide()
  42.     end
  43.     if _G["TokenFrame"] ~= nil then
  44.         _G["TokenFrame"]:Hide()
  45.     end
  46.     Panel:Show()
  47.     Panel.ScrollBox:SetScrollChild(Panel.Content)
  48. end)
  49.  
  50. hooksecurefunc("ToggleCharacter", function(tab, onlyShow)
  51.     if Panel:IsShown() then
  52.         Panel:Hide()
  53.     end
  54. end)
  55.  
  56. local Header = Panel.Content:CreateFontString()
  57. Header:SetFont("Fonts\\FRIZQT__.TTF", 35, "GameFontHighlightSmall")
  58. Header:SetPoint("TOP", 0, -10)
  59. Header:SetTextColor(0, 1, 0, 1)
  60. Header:SetText(TabName)
  61.  
  62. -- This is what extends the ScrollBox, it will auto extend as you position thing further down
  63. local EndOfScrollFrame = Panel.Content:CreateFontString()
  64. EndOfScrollFrame:SetFont("Fonts\\FRIZQT__.TTF", 20, "GameFontHighlightSmall")
  65. EndOfScrollFrame:SetPoint("TOP", 0, -1000)
  66. EndOfScrollFrame:SetTextColor(1, 0, 0, 1)
  67. EndOfScrollFrame:SetText("End of ScrollFrame")
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » Adding a ScrollFrame to a CharacterFrame tab


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