Thread Tools Display Modes
11/08/15, 06:48 AM   #1
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Need some help with understanding <Scroll> control

I have a plain <Scroll> control (XML source). No inherits="ZO_Scroll", since it only supports vertical scrolling and I want horizontal. No scrollbar.

Here's a picture of two Torchbug windows inspecting tbugTabWindow1Tabs:

tbugTabWindow1Tabs is the scroll control in the yellow box. It has 14 children: ActiveBg provides the dark background for the active tab "6", and children 2..14 are tab labels that were added dynamically -- intentionally too many to fit, you can see "_mouseSomething" is clipped on the right.

What I don't understand is that both extents.horizontal and extents.vertical are 0 (these are values returned by GetScrollExtents). And when I do /script tbugTabWindow1Tabs:SetHorizontalScroll(10), nothing happens. Offsets remain at 0.

I tried playing with SetScrollBounding, and when I set it to SCROLL_BOUNDING_UNBOUND and then SetHorizontalScroll(10), what happens is this: ActiveBg (the first child) is reanchored to the parent with offsetX=-10 and offsetY=-0 (not kidding, negative zero). All other children stay where they are.

Looking at how ZO_ScrollContainer is implemented, I'm beginning to think that the scroll control determines its inner extents solely from its first child, and that scrolling is actually implemented by shifting that child's anchor in the opposite direction.

Also does anyone know what different ScrollBounding values do? So far I've figured that UNBOUND allows you to SetVertical/HorizontalScroll beyond what GetScrollExtents returns. All other values (BOUND, CONTAINED, DEFAULT) seem to prevent that.
  Reply With Quote
11/08/15, 11:33 AM   #2
Wandamey
Guest
Posts: n/a
not sure if I understand one word of what you said, but i couldn't find this in your post / file :

ZO_HorizontalScrollList

thats what is used at the crafting station. could be helpful.
  Reply With Quote
11/08/15, 03:25 PM   #3
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by merlight View Post
I
What I don't understand is that both extents.horizontal and extents.vertical are 0 (these are values returned by GetScrollExtents). And when I do /script tbugTabWindow1Tabs:SetHorizontalScroll(10), nothing happens. Offsets remain at 0.
I'm guessing I must be missing something, but since your not inheriting, there is a lot of stuff missing isn't there? I see no scrollbar, nothing gets initialized (ZO_Scroll_Initialize) (even your tbugTabWindow1 has no .scroll or .scrollbar) I see no handlers to: handle extents changing, OnValueChanged, OnMouseWheel, no btns to move the scroll, exc... I understand you want it horizontal but I see no code to handle anything or maybe your just in the process of building it yourself? What did you expect it to do? Or better yet what are you trying to get it to do?


This probably isn't to helpful, I've never used this, but heres what I noticed using SetHorizontalScroll with:
SCROLL_BOUNDING_CONTAINED -- seems to change the extents & offset
SCROLL_BOUNDING_UNBOUND -- changes the offset only
SCROLL_BOUNDING_BOUND -- changes neither
SCROLL_BOUNDING_DEFAULT -- changes offset only

Changing the bounding allows changing the extent & offsets, but even then nothing happens. You said your 1st control reanchored & moved when you called SetHorizontalScroll() after changing the bounds? It didn't for me. Since I see no code for SetHorizontalScroll, I'm assuming it just sets a value but doesn't actually do anything else and I see no handlers to do anything even if those values change.

As Wandamey said, I would look at zo_horizontalscrolllist.lua & the clothier crafting station code: smithingcreation_shared.xml & smithing_common.xml.
  Reply With Quote
11/08/15, 03:55 PM   #4
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by circonian View Post
I'm guessing I must be missing something, but since your not inheriting, there is a lot of stuff missing isn't there?
Yes, it's only purpose so far has been clipping the tab labels so they don't overflow out of the window if you open too many. Scrolling behaviour is what I've been struggling with this weekend. It appears that making a container with resizeToFitDescendents="true" the only child of the scroll, and putting everything in the container is the way to go. E.g. ANIMATION_SCROLL then works on the scroll control.

SetScrollBounding is still a mystery to me, but luckily scrolling works without touching that

Originally Posted by circonian View Post
As Wandamey said, I would look at zo_horizontalscrolllist.lua & the clothier crafting station code: smithingcreation_shared.xml & smithing_common.xml.
ZO_HorizontalScrollList is of no use here. It's written for a fixed number of items of equal width.
  Reply With Quote
11/08/15, 04:01 PM   #5
Wandamey
Guest
Posts: n/a
Originally Posted by merlight View Post
ZO_HorizontalScrollList is of no use here. It's written for a fixed number of items of equal width.
and you can't resize your controls depending on the longer one and reinitialize your scrolllist depending on the situation?

Edit : actually that's what the smithing station does already, the table of listed items changes at each station/filter change for the corresponding table.
for the size of the elements idk though. I can't deny that they were all square.

I remember having emptied my crafting lists by accident while I was testing the smithing stations... shouldn't be too hard to reinit.

Last edited by Wandamey : 11/08/15 at 04:08 PM.
  Reply With Quote
11/08/15, 08:05 PM   #6
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by merlight View Post
ZO_HorizontalScrollList is of no use here. It's written for a fixed number of items of equal width.
Nah, you can do it:




XML:
Warning: Spoiler


LUA:
Warning: Spoiler



I didn't do this in the screenshots, didn't think of it until afterwords, but if you wanted (you probably would) you can change the DefaultEntryAnchor so that the "selected" control gets aligned left instead of center.
Lua Code:
  1. -- add:
  2. local LEFT_PADDING = 50
  3.  
  4. function patternList:SetDefaultEntryAnchor(control, offsetX)
  5.     --control:SetAnchor(CENTER, self.control, CENTER, offsetX)
  6.     control:SetAnchor(LEFT, self.control, LEFT, offsetX + LEFT_PADDING)
  7. end

Last edited by circonian : 11/09/15 at 05:30 PM.
  Reply With Quote
11/10/15, 06:08 AM   #7
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Interesting, I didn't know ZO_HorizontalScrollList can handle variable width items. And I didn't even think about item-wise scrolling (select next/previous). I only did area scrolling and you have to click to select another item. But I'm starting to like the idea of scrolling selection.
  Reply With Quote
11/10/15, 02:17 PM   #8
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by merlight View Post
Interesting, I didn't know ZO_HorizontalScrollList can handle variable width items. And I didn't even think about item-wise scrolling (select next/previous). I only did area scrolling and you have to click to select another item. But I'm starting to like the idea of scrolling selection.
You could still select items by clicking them this way too. You don't even have to handle the clicks, just make the slotTemplate mouseEnabled & the rest is handled for you.

xml Code:
  1. <Control name="HorizontalScroll_HList_SlotTemplate" virtual="true" mouseEnabled="true">



You can also scroll with the mouse wheel or click/drag the bar to scroll through it, its all handled for you. If you wanted you could even hide the big Left/Right buttons.
  Reply With Quote
05/10/16, 04:24 PM   #9
Letho
AddOn Author - Click to view addons
Join Date: Apr 2016
Posts: 238
Heyho,

I'm currently having trouble setting up a scrollable area and stumbled upon this thread as i did some research with google. I'd like to set up a scrollable area from scratch, that means not using any inherited or predefined control/code written by zenimax. Sadly I have no clue how the scroll control works. I found a cheap and dirty workaround, but it's not really working well for it throws some lua errors:

Here is what i did:
1. defined a scrollbar using a slider-control.
2. defined a control of type "CT_SCROLL" (name="ScrollChild") and added a regular CT_CONTROL (name="ScrollingContainer") to it.
3. Using the slider's "OnValueChanged" - event i simply modify the "ScrollingContainer"'s anchor-offset by clearing it's anchors and adding a new one with the new y-offset. Because ScrollingContainer is a child-element of the CT_SCROLL every content displayed "outside" the CT_SCOLL wont be displayed for CT_CONTROL seems to behave like an HTML div-container with overflow:hidden.

This results in the desired behaviour but also throws the "too many anchors processed" lua error - not to mention the low performance.

I'd really like how to implement scrolling areas in a proper way, could anybody help me?

Here's the code:

Lua Code:
  1. function AuraMastery:Tex() -- Shows Window with all icon textures on the screen
  2.     local container = WM:CreateTopLevelWindow("AMTextureContainer"); -- Main container
  3.    
  4.     local bg         = WM:CreateControl("$(parent)_Backdrop", container, CT_BACKDROP);
  5.  
  6.     local oX = 0;
  7.     local oY = 0;
  8.  
  9.     container:SetClampedToScreen(true);
  10.     container:SetDimensions(1600, 900);
  11.     container:ClearAnchors();
  12.     container:SetAnchor(CENTER, GuiRoot, CENTER);
  13.     container:SetAlpha(1);
  14.     container:SetMovable(true);
  15.     container:SetHidden(false);
  16.     container:SetMouseEnabled(true);
  17.  
  18.     bg:SetAnchorFill();
  19.     bg:SetCenterColor(0,0,0,.4);
  20.     bg:SetEdgeTexture(nil, 1, 1, 1, 0);
  21.     bg:SetEdgeColor(1,1,1,.12);
  22.  
  23.     -- Scrollable area that hides everything that expands beyond it's own size
  24.     local scrollChild = WM:CreateControl("$(parent)_ScrollChild", container, CT_SCROLL);
  25.     scrollChild:SetDimensions(1575,900);
  26.     scrollChild:SetAnchor(TOPLEFT, container, TOPLEFT, 0, 0);
  27.     scrollChild:SetScrollBounding(SCROLL_BOUNDING_CONTAINED);
  28.  
  29.     scrollChild.bg = WM:CreateControl("$(parent)_Backdrop", scrollChild, CT_BACKDROP);
  30.     scrollChild.bg:SetAnchorFill();
  31.     scrollChild.bg:SetCenterColor(1,0,0,.1);
  32.     scrollChild.bg:SetEdgeTexture(nil, 1, 1, 1, 0);
  33.     scrollChild.bg:SetEdgeColor(0,0,0,0);
  34.  
  35.         -- This containers Y-Offset will be modified by our scrollbar-value, hiding it's parts that expand beyong the CT_SCROLL's size
  36.     local scrollContainer = WM:CreateControl("AuraMastery_ScrollContainer", scrollChild, CT_CONTROL)
  37.     scrollContainer:SetDimensions(1575,900);
  38.     scrollContainer:SetAnchor(TOPLEFT, container, TOPLEFT, 0, -(padding+iconSize));
  39.     scrollContainer:SetResizeToFitDescendents(true);
  40.     scrollContainer.bg = WM:CreateControl("$(parent)_Backdrop", scrollContainer, CT_BACKDROP);
  41.     scrollContainer.bg:SetAnchorFill();
  42.     scrollContainer.bg:SetCenterColor(0,0,1,.1);
  43.     scrollContainer.bg:SetEdgeTexture(nil, 1, 1, 1, 0);
  44.     scrollContainer.bg:SetEdgeColor(0,0,0,0);
  45.  
  46.     -- SCROLLBAR
  47.     local scrollBar = WM:CreateControl("$(parent)_ScrollBar", container, CT_SLIDER);
  48.     scrollBar:SetDimensions(25, 900);
  49.     scrollBar:SetAnchor(TOPRIGHT, container, TOPRIGHT);
  50.     scrollBar:SetOrientation(ORIENTATION_VERTICAL);
  51.     scrollBar:SetMouseEnabled(true);
  52.     scrollBar:SetMinMax(0,900);
  53.     scrollBar:SetThumbTexture(nil,nil, nil, 25, 25);
  54.     scrollBar:SetValueStep(padding+iconSize);
  55.         -- backdrop
  56.         scrollBar.bg = WM:CreateControl("$(parent)_Backdrop", scrollBar, CT_BACKDROP);
  57.         scrollBar.bg:SetAnchor(TOPLEFT, slider, TOPLEFT, 0, 4)
  58.         scrollBar.bg:SetAnchor(BOTTOMRIGHT, slider, BOTTOMRIGHT, 0, -4)
  59.         scrollBar.bg:SetCenterColor(0,0,0);
  60.         scrollBar.bg:SetEdgeTexture(nil, 1, 1, 1, 0);
  61.         scrollBar.bg:SetEdgeColor(0,0,0,0);
  62.  
  63.     scrollBar:SetHandler("OnValueChanged", function(self) AuraMastery:Scroll(); d(self:GetValue()); end);
  64.  
  65.          -- self.icons contains that path to every texture of type "icon" in the game (e.g.:  [1] = Esoui/art/icons/.../textureName.dds
  66.     for k,v in pairs(self.icons) do
  67.         local modX = (k-1)%29; -- display only 29 icons of size 48px per row!
  68.         local modY = math.floor((k-1)/29);
  69.  
  70.         oX = (modX*iconSize)+((modX+1)*padding);
  71.         oY = (modY*iconSize)+((modY+1)*padding);
  72.  
  73.                 -- button is needed for displaying a tooltip on mouseOver (doesnt work on CT_TEXTURE)
  74.         local iconContainer = WM:CreateControl("Icon"..k, scrollContainer, CT_BUTTON);
  75.         iconContainer:SetDimensions(iconSize, iconSize);
  76.         iconContainer:SetAnchor(TOPLEFT, scrollContainer, TOPLEFT, oX, oY);
  77.         iconContainer.iconnr = k;
  78.  
  79.                 -- the icon texture...
  80.         local icon = WM:CreateControl("$(parent)_Texture"..k, iconContainer, CT_TEXTURE);
  81.         icon:SetAnchorFill();
  82.         icon:SetDimensions(iconSize,iconSize);
  83.         icon:SetTexture(v);
  84.                 -- ... and it's tooltip; SetHidden(false) on mouseover
  85.         local iconTooltip = WM:CreateControl("$(parent)_Tooltip", iconContainer, CT_CONTROL);
  86.         iconTooltip:SetHidden(true);
  87.         iconTooltip:SetDimensions(320,48);
  88.         iconTooltip:SetAnchor(BOTTOM, iconContainer, TOP);
  89.  
  90.         iconTooltip.bg = WM:CreateControl("$(parent)_Backdrop", iconTooltip, CT_BACKDROP);
  91.         iconTooltip.bg:SetAnchorFill();
  92.         iconTooltip.bg:SetDrawLayer(1);
  93.         iconTooltip.bg:SetCenterColor(0,0,0,1);
  94.         iconTooltip.bg:SetEdgeTexture(nil,1,1,1,0);
  95.         iconTooltip.bg:SetEdgeColor(1,1,1,.12);
  96.  
  97.         iconTooltip.label = WM:CreateControl("$(parent)_Label", iconTooltip, CT_LABEL);
  98.         iconTooltip.label:SetAnchorFill();
  99.         iconTooltip.label:SetFont("$(BOLD_FONT)|18|outline");
  100.         iconTooltip.label:SetColor(1,1,1,1);
  101.         iconTooltip.label:SetText(v);
  102.  
  103.         iconContainer:SetHandler("OnMouseEnter", function(self) AuraMastery:Tooltip(self.iconnr); end);
  104.         iconContainer:SetHandler("OnMouseExit", function(self) AuraMastery:Tooltip(self.iconnr); end);
  105.     end
  106.  
  107. end
  108.  
  109. function AuraMastery:Scroll()
  110.     local offset = WM:GetControlByName("AMTextureContainer_ScrollBar"):GetValue();
  111.     local control = WM:GetControlByName("AuraMastery_ScrollContainer");
  112.     control:ClearAnchors();
  113.     control:SetSimpleAnchor(scrollChild, 0, -offset);
  114. end









Scrolled down one step (1 step = height of one row of icons, padding included):


Cheers,
Letho

Last edited by Letho : 05/10/16 at 05:08 PM. Reason: adding code
  Reply With Quote
05/10/16, 06:11 PM   #10
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by Letho View Post
I'd like to set up a scrollable area from scratch, that means not using any inherited or predefined control/code written by zenimax.
I'd advise you to try using ZO_ScrollList. It's almost guaranteed to perform better.

In your code above, you're creating as many icon controls as there are icons in your dataset. And each time you scroll, all of them need to follow their anchor to the container; including those not currently visible.

ZO_ScrollList, on the other hand, creates only enough row controls to fill the area; and reuses them as you scroll around. That means fewer controls overall, and fewer anchor updates when scrolling.
  Reply With Quote
05/11/16, 04:35 AM   #11
Letho
AddOn Author - Click to view addons
Join Date: Apr 2016
Posts: 238
Hey merlight, thank you for your quick response! I was afraid that would be the case, the actual reason for me not to use the Z_ScrollList is I havent been able to get it running, nor understanding the whole code inside it's lua file :/
I don't even understand the principle behind it's mechanic, I mean the princible I use in my code is quite easy: move the child Elements of a control that hides all of its child element's overflow by modifying the child elements anchor-x/y-offsets^^
Could u / anybody explain how ZO_ScrollList implements the scrolling behaviour and what functions u need to set up a simple scrolling container? I've read through this thread and some others and could reproduce your problems with SetScrollBounding. At least I was finally able to "unlock" (= getting it to save values different from 0) the SetVerticalScroll() - function, but it did not change any displayed content.

Another suspicion/fear I have is that ESOs controls are not meant to scroll areas that contain as many items as i want to be displayed :/
Within my implementation the "too many anchors processed" - error is even thrown if i reduce my dataset to 10 elements

Last edited by Letho : 05/11/16 at 04:41 AM.
  Reply With Quote
05/11/16, 04:55 AM   #12
Ayantir
 
Ayantir's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 1,019
If you want to display stuff in a controll which is scrollable, just do :


Lua Code:
  1. <TopLevelControl name="MyXMLControl" hidden="true">
  2.     <Controls>
  3.  
  4.         <Control name="$(parent)Container" inherits="ZO_ScrollContainer">
  5.             <OnInitialized>
  6.                 ZO_Scroll_Initialize(self)
  7.             </OnInitialized>
  8.             <Dimensions x="850" y="630"/>
  9.             <Anchor point="BOTTOMLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="50" offsetY="650" />
  10.         </Control>
  11.  
  12.         <Label name="$(parent)Blabla">
  13.             <Dimensions x="830" />
  14.             <OnInitialized>
  15.                 self:SetParent(GetControl("MyXMLControlContainerScrollChild"))
  16.                 self:SetAnchor(TOPLEFT, MyXMLControlContainerScrollChild, TOPLEFT, 4, 4)
  17.             </OnInitialized>
  18.         </Label>
  19.  
  20.         <!-- Add other controlls here, same as previous -->
  21.        
  22.     <Controls>
  23. </TopLevelControl>



















If you want to create a Scroll list (Aka : A list of data which is scrollable)

XML

A row :

Lua Code:
  1. <Control name="KillCounterKillerRowTemplate" virtual="true" mouseEnabled="true">
  2.     <OnMouseEnter>
  3.         KillCounter_HoverRowOfDeaths(self)
  4.     </OnMouseEnter>
  5.     <OnMouseExit>
  6.         KillCounter_ExitRowOfDeaths(self)
  7.     </OnMouseExit>
  8.     <Dimensions x="600" y="30" />
  9.     <Controls>
  10.         <Texture name="$(parent)BG" inherits="ZO_ThinListBgStrip" />
  11.        
  12.         <Texture name="$(parent)Alliance" font="ZoFontGame" verticalAlignment="CENTER">
  13.             <Dimensions x="32" y="32" />
  14.             <Anchor point="TOPLEFT" relativeTo="$(parent)" />
  15.         </Texture>
  16.         <Texture name="$(parent)Rank" font="ZoFontGame" verticalAlignment="CENTER">
  17.             <Dimensions x="32" y="32" />
  18.             <Anchor point="TOPLEFT" relativeTo="$(parent)Alliance" relativePoint="TOPRIGHT" offsetX="5"/>
  19.         </Texture>
  20.         <Texture name="$(parent)PlayerClass" font="ZoFontGame" verticalAlignment="CENTER">
  21.             <Dimensions x="32" y="32" />
  22.             <Anchor point="TOPLEFT" relativeTo="$(parent)Rank" relativePoint="TOPRIGHT" offsetX="5"/>
  23.             <OnMouseEnter>
  24.                 KillCounter_Deaths_PlayerClassOnMouseEnter(self)
  25.             </OnMouseEnter>
  26.             <OnMouseExit>
  27.                 KillCounter_Deaths_PlayerClassOnMouseExit(self)
  28.             </OnMouseExit>
  29.         </Texture>
  30.         <Texture name="$(parent)Veteran" mouseEnabled="true" layer="OVERLAY">
  31.             <Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$(parent)PlayerClass" offsetX="5" />
  32.             <Dimensions x="32" y="32"/>
  33.         </Texture>
  34.         <Label name="$(parent)PlayerLevel" font="ZoFontGame" verticalAlignment="CENTER">
  35.             <Dimensions x="32" y="32" />
  36.             <Anchor point="TOPLEFT" relativeTo="$(parent)Veteran" relativePoint="TOPRIGHT"/>
  37.         </Label>
  38.         <Label name="$(parent)PlayerName" font="ZoFontGame" verticalAlignment="CENTER">
  39.             <Dimensions x="150" y="32" />
  40.             <Anchor point="TOPLEFT" relativeTo="$(parent)PlayerLevel" relativePoint="TOPRIGHT"/>
  41.         </Label>
  42.         <Label name="$(parent)PlayerAccount" font="ZoFontGame" verticalAlignment="CENTER">
  43.             <Dimensions x="150" y="32" />
  44.             <Anchor point="TOPLEFT" relativeTo="$(parent)PlayerName" relativePoint="TOPRIGHT" />
  45.         </Label>
  46.         <Label name="$(parent)PlayerDeaths" font="ZoFontGame" verticalAlignment="CENTER">
  47.             <Dimensions x="75" y="32" />
  48.             <Anchor point="TOPLEFT" relativeTo="$(parent)PlayerAccount" relativePoint="TOPRIGHT" />
  49.         </Label>
  50.        
  51.     </Controls>
  52. </Control>



The list itself :

In the list we define the headers and the list.
Here I used sortable headers (the ones with the little triangles to sort).
ZO_SortHeader_Initialize is used to make an header with a name
ZO_SortHeader_InitializeArrowHeader is used to make an header without

Lua Code:
  1. <TopLevelControl name="Scene_KC_Menu_Deaths" inherits="ZO_RightPanelFootPrint" hidden="true">
  2.     <Controls>
  3.        
  4.         <Control name="$(parent)Headers">
  5.             <Dimensions x="600" y="32" />
  6.             <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="300" offsetY="50"/>
  7.             <Controls>
  8.            
  9.                 <Control name="$(parent)Alliance" inherits="ZO_SortHeaderIcon">
  10.                     <OnInitialized>
  11.                         ZO_SortHeader_InitializeArrowHeader(self, "alliance", ZO_SORT_ORDER_DOWN)
  12.                         ZO_SortHeader_SetTooltip(self, GetString(SI_FRIENDS_LIST_PANEL_TOOLTIP_ALLIANCE))
  13.                     </OnInitialized>
  14.                     <Anchor point="TOPLEFT" relativeTo="$(parent)" offsetX="12"/>
  15.                     <Dimensions x="16" y="32" />
  16.                 </Control>
  17.                
  18.                 <Control name="$(parent)Rank" inherits="ZO_SortHeaderIcon">
  19.                     <OnInitialized>
  20.                         ZO_SortHeader_InitializeArrowHeader(self, "rank", ZO_SORT_ORDER_DOWN)
  21.                         ZO_SortHeader_SetTooltip(self, GetString(SI_STATS_ALLIANCE_RANK))
  22.                     </OnInitialized>
  23.                     <Anchor point="TOPLEFT" relativeTo="$(parent)Alliance" relativePoint="TOPRIGHT" offsetX="17"/>
  24.                     <Dimensions x="16" y="32" />
  25.                 </Control>
  26.                
  27.                 <Control name="$(parent)PlayerClass" inherits="ZO_SortHeaderIcon">
  28.                     <OnInitialized>
  29.                         ZO_SortHeader_InitializeArrowHeader(self, "playerclass", ZO_SORT_ORDER_DOWN)
  30.                         ZO_SortHeader_SetTooltip(self, GetString(SI_FRIENDS_LIST_PANEL_TOOLTIP_CLASS))
  31.                     </OnInitialized>
  32.                     <Anchor point="TOPLEFT" relativeTo="$(parent)Rank" relativePoint="TOPRIGHT" offsetX="20"/>
  33.                     <Dimensions x="16" y="32" />
  34.                 </Control>
  35.                
  36.                 <Control name="$(parent)PlayerLevel" inherits="ZO_SortHeaderIcon">
  37.                     <OnInitialized>
  38.                         ZO_SortHeader_InitializeArrowHeader(self, "playerlevel", ZO_SORT_ORDER_DOWN)
  39.                         ZO_SortHeader_SetTooltip(self, GetString(SI_FRIENDS_LIST_PANEL_TOOLTIP_LEVEL))
  40.                     </OnInitialized>
  41.                     <Anchor point="TOPLEFT" relativeTo="$(parent)PlayerClass" relativePoint="TOPRIGHT" offsetX="28"/>
  42.                     <Dimensions x="16" y="32" />
  43.                 </Control>
  44.                
  45.                 <Control name="$(parent)PlayerName" inherits="ZO_SortHeader">
  46.                     <OnInitialized>
  47.                         ZO_SortHeader_Initialize(self, "Name", "playername", ZO_SORT_ORDER_DOWN, TEXT_ALIGN_LEFT, "ZoFontGameLargeBold")
  48.                     </OnInitialized>
  49.                     <Anchor point="TOPLEFT" relativeTo="$(parent)PlayerLevel" relativePoint="TOPRIGHT" offsetX="35"/>
  50.                     <Dimensions x="150" y="32" />
  51.                 </Control>
  52.                
  53.                 <Control name="$(parent)PlayerAccount" inherits="ZO_SortHeader">
  54.                     <OnInitialized>
  55.                         ZO_SortHeader_Initialize(self, "Account", "playeraccount", ZO_SORT_ORDER_DOWN, TEXT_ALIGN_LEFT, "ZoFontGameLargeBold")
  56.                     </OnInitialized>
  57.                     <Anchor point="TOPLEFT" relativeTo="$(parent)PlayerName" relativePoint="TOPRIGHT"/>
  58.                     <Dimensions x="150" y="32" />
  59.                 </Control>
  60.                
  61.                 <Control name="$(parent)PlayerDeaths" inherits="ZO_SortHeader">
  62.                     <OnInitialized>
  63.                         ZO_SortHeader_Initialize(self, "Deaths", "deaths", ZO_SORT_ORDER_DOWN, TEXT_ALIGN_LEFT, "ZoFontGameLargeBold")
  64.                     </OnInitialized>
  65.                     <Anchor point="TOPLEFT" relativeTo="$(parent)PlayerAccount" relativePoint="TOPRIGHT"/>
  66.                     <Dimensions x="75" y="32" />
  67.                 </Control>
  68.                
  69.             </Controls>
  70.         </Control>
  71.        
  72.         <Control name="$(parent)List" inherits="ZO_ScrollList">
  73.             <Dimensions x="600" y="575" />
  74.             <Anchor point="TOPLEFT" relativeTo="$(parent)Headers" relativePoint="TOPLEFT" offsetX="0" offsetY="40" />
  75.         </Control>
  76.        
  77.     </Controls>
  78. </TopLevelControl>


Then, in Lua :


Lua Code:
  1. local myList = ZO_SortFilterList:Subclass()
  2.  
  3. function myList:New(control)
  4.    
  5.     ZO_SortFilterList.InitializeSortFilterList(self, control)
  6.    
  7.     -- tiebreaker  is used when values are equal. You can also add isNumeric = true if needed.
  8.     local sorterKeys =
  9.     {
  10.         ["deaths"] = {},
  11.         ["alliance"] = {tiebreaker = "deaths"},
  12.         ["rank"] = {tiebreaker = "deaths"},
  13.         ["playername"] = {tiebreaker = "deaths"},
  14.         ["playeraccount"] = {tiebreaker = "deaths"},
  15.         ["playerclass"] = {tiebreaker = "deaths"},
  16.         ["veteranrank"] = { tiebreaker = "deaths"},
  17.         ["playerlevel"] = { tiebreaker = "veteranrank"},
  18.     }
  19.    
  20.     self.masterList = {}
  21.     ZO_ScrollList_AddDataType(self.list, 1, "KillCounterKillerRowTemplate", 32, function(control, data) self:SetupEntry(control, data) end) -- Add my row
  22.     ZO_ScrollList_EnableHighlight(self.list, "ZO_ThinListHighlight") -- Enable the highlight (the turquoise color)
  23.     self.currentSortKey = "deaths" -- defaut sort
  24.    
  25.     self.sortFunction = function(listEntry1, listEntry2) return ZO_TableOrderingFunction(listEntry1.data, listEntry2.data, self.currentSortKey, sorterKeys, self.currentSortOrder) end -- my sort function
  26.     self:SetAlternateRowBackgrounds(true) -- Alternate background, one dark, one grey
  27.    
  28.     return self
  29.    
  30. end
  31.  
  32. function myList:SetupEntry(control, data)
  33.    
  34.     -- Setup a row
  35.    
  36.     control.data = data
  37.     control.alliance = GetControl(control, "Alliance")
  38.     control.rank = GetControl(control, "Rank")
  39.     control.playername = GetControl(control, "PlayerName")
  40.     control.playeraccount = GetControl(control, "PlayerAccount")
  41.     control.playerclass = GetControl(control, "PlayerClass")
  42.     control.playerlevel = GetControl(control, "PlayerLevel")
  43.     control.deaths = GetControl(control, "PlayerDeaths")
  44.     local veteran = GetControl(control, "Veteran")
  45.    
  46.     control.alliance:SetTexture(GetAllianceSymbolIcon(data.alliance))
  47.    
  48.     if data.rank >= 0 and data.rank <= 50 then
  49.         control.rank:SetTexture(GetAvARankIcon(data.rank))
  50.     else
  51.         control.rank:SetHidden(true)
  52.     end
  53.    
  54.     if GetClassIcon(data.playerclass) then
  55.         control.playerclass:SetTexture(GetClassIcon(data.playerclass))
  56.     else
  57.         control.playerclass:SetHidden(true)
  58.     end
  59.    
  60.     control.playerlevel:SetText(GetLevelOrVeteranRankStringNoIcon(data.playerlevel, data.veteranrank))
  61.    
  62.     if data.veteranrank and data.veteranrank > 0 then
  63.         veteran:SetTexture(GetVeteranRankIcon())
  64.     else
  65.         veteran:SetHidden(true)
  66.     end
  67.    
  68.     control.playername:SetText(data.playername)
  69.     control.playeraccount:SetText(data.playeraccount)
  70.     control.deaths:SetText(data.deaths)
  71.    
  72.     ZO_SortFilterList.SetupRow(self, control, data)
  73.    
  74. end
  75.  
  76. function myList:BuildMasterList()
  77.     self.masterList = {}
  78.     local killingList = db.killingList
  79.     if killingList then
  80.         for k, v in ipairs(killingList) do
  81.             local data = v
  82.             table.insert(self.masterList, data)
  83.         end
  84.     end
  85.    
  86. end
  87.  
  88. function myList:SortScrollList()
  89.     local scrollData = ZO_ScrollList_GetDataList(self.list)
  90.     table.sort(scrollData, self.sortFunction)
  91. end
  92.  
  93. function myList:FilterScrollList()
  94.    
  95.     -- If you want to add a filter
  96.    
  97.     local scrollData = ZO_ScrollList_GetDataList(self.list)
  98.     ZO_ClearNumericallyIndexedTable(scrollData)
  99.  
  100.     for i = 1, #self.masterList do
  101.         local data = self.masterList[i]
  102.         table.insert(scrollData, ZO_ScrollList_CreateDataEntry(1, data))
  103.     end
  104. end
  105.  
  106. function KillCounter_HoverRowOfDeaths(control)
  107.     myList:Row_OnMouseEnter(control)
  108. end
  109.  
  110. function KillCounter_ExitRowOfDeaths(control)
  111.     myList:Row_OnMouseExit(control)
  112. end



->



Last edited by Ayantir : 05/11/16 at 05:18 AM.
  Reply With Quote
05/11/16, 05:14 AM   #13
Letho
AddOn Author - Click to view addons
Join Date: Apr 2016
Posts: 238
Hi Ayantir, thx for your help! I'll just copy it to my notepad++ and try to understand and reproduce it! (I always have to see the actual result ingame in order to understand code^^)
  Reply With Quote
05/11/16, 05:18 AM   #14
Letho
AddOn Author - Click to view addons
Join Date: Apr 2016
Posts: 238
Ok, first question I have:

lua Code:
  1. <OnInitialized>
  2.                   self:SetParent(GetControl("MyXMLControlContainerScrollChild"))
  3.                   self:SetAnchor(TOPLEFT, MyXMLControlContainerScrollChild, TOPLEFT, 4, 4)
  4.              </OnInitialized>

What control is "MyXMLControlContainerScrollChild"?

Cheers
  Reply With Quote
05/11/16, 05:22 AM   #15
Ayantir
 
Ayantir's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 1,019
What control is "MyXMLControlContainerScrollChild"?
Lua Code:
  1. <TopLevelControl name="MyXMLControl" hidden="true">
  2.     <Controls>

MyXMLControl....

Lua Code:
  1. <Control name="$(parent)Container" inherits="ZO_ScrollContainer">
  2.             <OnInitialized>

MyXMLControlContainer ...


ScrollChild is added by inherits="ZO_ScrollContainer"

so MyXMLControlContainerScrollChild is the control which will host all the data you want to be scrollable. (look at the pict I posted)
  Reply With Quote
05/11/16, 06:34 AM   #16
Letho
AddOn Author - Click to view addons
Join Date: Apr 2016
Posts: 238
Hey, just wanted to thank u for your help! I'm currently eating myself through the code, modifying my containers to get some (visual) understanding of what each container does^^ I'm afraid I'm far away from understanding even the basics for I only know WoW Lua (not the xml widget api) and generic XHTML and I actually have no clue what the rules for ESOs XAML interface are. But your examples help a lot

I'm sure there will be more questions in the future, I'll just post them here if u dont mind, your help is much appreciated, very cool that places like this exist!
  Reply With Quote
05/11/16, 07:40 AM   #17
Letho
AddOn Author - Click to view addons
Join Date: Apr 2016
Posts: 238
Ok I finally managed setting up a working scroll container:

lua Code:
  1. <GuiXml>
  2.     <Controls>
  3.  
  4. <!-- This is my parent container containing the scrollable container -->
  5.         <TopLevelControl name="AuraMasteryMenuContainer" clampedToScreen="true" mouseEnabled="true" movable="true" hidden="true">
  6.             <Dimensions x="1280" y="768" />
  7.             <Anchor point="CENTER" relativeTo="GuiRoot" relativePoint="CENTER" />
  8.             <Controls>
  9.                 <Backdrop name="$(parent)_Backdrop" centerColor="CC000000" edgeColor="1F1F1F">
  10.                     <AnchorFill />
  11.                     <Edge edgeSize= "1" />
  12.                 </Backdrop>
  13.  
  14.  
  15. <!-- SCrollable container that will contain all the nice little icons that the user will be able to scroll through -->
  16.         <Control name="$(parent)ScrollExample" inherits="ZO_ScrollContainer">
  17.              <OnInitialized>
  18.                   ZO_Scroll_Initialize(self)
  19.              </OnInitialized>
  20.              <Dimensions x="850" y="630"/>
  21.              <Anchor point="BOTTOMLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="50" offsetY="650" />
  22.         </Control>

And the .lua file for adding one of the above mentioned icons to the scroll container:
lua Code:
  1. local parent = WM:GetControlByName("AuraMasteryMenuContainerScrollExampleScrollChild");
  2.         d(tostring(parent));
  3.         local icon = WM:CreateControl("$(parent)_Texture", parent, CT_TEXTURE);
  4.         icon:SetParent(parent);
  5.         icon:SetAnchor(TOPLEFT, parent, TOPLEFT, 4, 4);
  6.         icon:SetDimensions(iconSize,iconSize);
  7.         icon:SetTexture("esoui/art/icons/ability_1handed_001.dds");


This code results in the icon texture being displayed, but no scroll bar and no background for the scrollcontainer.

In this post (http://www.esoui.com/forums/showpost.php?p=10826) u stated that

Originally Posted by merlight View Post
ZO_ScrollContainer is a control that contains the slider bar, buttons and the scrolled area, which is named "$(parent)ScrollChild".
I inspected the container with the addon "zgoo" and the container does not contain a scrollbar.
Did i do something wrong or did Zenimax change that? How do i set up a scollbar and associate it or it's event handler OnValueChanged to the container?

P.S.: I didn't get that ZO_ScrollContainer and ZO_ScrollList are two different things, that confused me

Last edited by Letho : 05/11/16 at 10:58 AM.
  Reply With Quote
05/11/16, 12:54 PM   #18
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by Letho View Post
I don't even understand the principle behind it's mechanic, I mean the princible I use in my code is quite easy: move the child Elements of a control that hides all of its child element's overflow by modifying the child elements anchor-x/y-offsets^^
The principle behind ZO_ScrollList is separating data from controls. That way you can have thousands of data items in a list, and only a bunch of controls to display them (well in your case, there'll be a lot of icons visible at once, but still less than all of them, right?).

The simplest use of ZO_ScrollList I could quickly find is AbilityList. Here it's initialized with two row types, and
here it's filled with data. All you need is a control created from the ZO_ScrollList template, either in XML or in Lua:
Lua Code:
  1. local list = wm:CreateControlFromVirtual("$(parent)List", parent, "ZO_ScrollList")
and a template for your row type, that must be defined in XML (unless you replace the row pool's factory function).

Another example is in LibAddonMenu.

Originally Posted by Letho View Post
Within my implementation the "too many anchors processed" - error is even thrown if i reduce my dataset to 10 elements
That usually happens when your anchors have circular dependency. Which includes a kind of chicken&egg problem when a container control has resizeToFitDescendents="true" and its children are trying to fill the parent.
  Reply With Quote
05/11/16, 01:01 PM   #19
Letho
AddOn Author - Click to view addons
Join Date: Apr 2016
Posts: 238
I understand, would u advice not to use ZO_ScrollContainer but ZO_ScrollList instead? I find the container version far more simple :/

Can you describe how to set up a scrollbar for a ZO_ScrollContainer and how to use its scrolling event handler?

Btw. are these controls and it's functions documented somewhere? Getting help is always good, but i dont want you to get the impression im just asking here becuz im too lazy to read a documentation I just did research for the last two days and i'm really getting more and more desperate, especially if i consider my addon is nearly finished with the scroll container problem being the only thing standing in my way ;D
  Reply With Quote
05/11/16, 02:23 PM   #20
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by Letho View Post
I understand, would u advice not to use ZO_ScrollContainer but ZO_ScrollList instead? I find the container version far more simple :/

Can you describe how to set up a scrollbar for a ZO_ScrollContainer and how to use its scrolling event handler?
I've never used ZO_ScrollContainer, and I wouldn't use it in this case, either. Here's how I see it:
- ZO_ScrollContainer for UI widgets -- a number of controls, often of different types, shapes and sizes; each with a specific purpose -- a good example is LibAddonMenu's panel control
- ZO_ScrollList for lists of similar items -- like inventory; here the controls (rows) are not special, any of them can display any data item. You wouldn't want the guild bank UI to actually contain 500 rows. ZO_ScrollList does all the work required to create the illusion of there being 500 rows, while it only constructs as many row controls as are simultaneously visible.

You have N icons, M per row. So you'll add ceil(N/M) data rows to the list (simple tables containing up to M texture paths), and your row control setup function will set the textures on icon controls in the row.

Originally Posted by Letho View Post
Btw. are these controls and it's functions documented somewhere? Getting help is always good, but i dont want you to get the impression im just asking here becuz im too lazy to read a documentation I just did research for the last two days and i'm really getting more and more desperate, especially if i consider my addon is nearly finished with the scroll container problem being the only thing standing in my way ;D
We've all learned from The Source and/or other add-ons Don't get overwhelmed, you'll find your way around much more easily after you get used to how the UI is structured (I think 83% of it are lists).
  Reply With Quote

ESOUI » Developer Discussions » Lua/XML Help » Need some help with understanding <Scroll> control


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