Thread Tools Display Modes
10/08/14, 10:56 PM   #1
Argusus
AddOn Author - Click to view addons
Join Date: Sep 2014
Posts: 120
Multiple ZO_ScrollList in same window

Hello,

I'm having trouble creating 2 ZO_SortFilterList objects in the same window. I have tried to create 2 scrollist / ZO_SortFilterList's based on the "ScrollListExample" from the developer utilities page. I have duplicated the XML to define the scrolllist and the Lua to create another ZO_SortFilterList but i'm getting the error message below.

is there a way to house 2 ZO_SortFilterLists in 1 window?

Code:
Failed to create control 'ScrollListExampleHeadersArrow'.  Duplicate name

Last edited by Argusus : 10/08/14 at 11:11 PM.
  Reply With Quote
10/09/14, 04:05 AM   #2
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Just give them different names. You probably named both "ScrollListExample".

And if you want the lists to look the same, only have different data, it's best to make it a virtual control, so you don't need to copy tons of xml over and over.
xml Code:
  1. <Control name="MyScrollListTemplate" virtual="true">
  2. ...
  3. </Control>
Lua Code:
  1. function MyList:New(name, parent)
  2.     local control = CreateControlFromVirtual(name, parent, "MyScrollListTemplate")
  3.     local list = ZO_SortFilterList.New(self, control)
  4.     list:Initialize()
  5.     return list
  6. end
  7.  
  8. list1 = MyList:New("$(parent)List1", myTopLevelControl)
  9. list2 = MyList:New("$(parent)List2", myTopLevelControl)
  Reply With Quote
10/09/14, 06:03 AM   #3
Argusus
AddOn Author - Click to view addons
Join Date: Sep 2014
Posts: 120
Originally Posted by merlight View Post
Just give them different names. You probably named both "ScrollListExample".

And if you want the lists to look the same, only have different data, it's best to make it a virtual control, so you don't need to copy tons of xml over and over.
xml Code:
  1. <Control name="MyScrollListTemplate" virtual="true">
  2. ...
  3. </Control>
Lua Code:
  1. function MyList:New(name, parent)
  2.     local control = CreateControlFromVirtual(name, parent, "MyScrollListTemplate")
  3.     local list = ZO_SortFilterList.New(self, control)
  4.     list:Initialize()
  5.     return list
  6. end
  7.  
  8. list1 = MyList:New("$(parent)List1", myTopLevelControl)
  9. list2 = MyList:New("$(parent)List2", myTopLevelControl)

I might have to go the template route down the road. my issue needs to be centering around the "second" paramater in the contructor. the error happens on the second call to the scroll list. it looks like that "ScrollListExampleMainWindow" is the parent of the control and the "ScrollListExampleMainWindowHeadersArrow" error, is render based on the parent named rather than the control name defined in XML.

Code:
function UnitList:New()
	local units = ZO_SortFilterList.New(self, ScrollListExampleMainWindow)
	units:Initialize()
	return units
end

function UnitList2:New()
	local units = ZO_SortFilterList.New(self, ScrollListExampleMainWindow)
	units:Initialize()
	return units
end
  Reply With Quote
10/09/14, 08:42 AM   #4
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
ScrollListExampleMainWindow is the scroll list control. ZO_SortFilterList is a class, of which you create an instance that wraps the control and adds some children (like the header Arrow) and functionality. In order to have two lists, you need two controls to represent them. That is, each ZO_SortFilterList.New(self, control) call must specify a different control. In my previous example I achieved that by creating the control from a template.
  Reply With Quote
10/09/14, 10:43 AM   #5
Argusus
AddOn Author - Click to view addons
Join Date: Sep 2014
Posts: 120
Originally Posted by merlight View Post
ScrollListExampleMainWindow is the scroll list control. ZO_SortFilterList is a class, of which you create an instance that wraps the control and adds some children (like the header Arrow) and functionality. In order to have two lists, you need two controls to represent them. That is, each ZO_SortFilterList.New(self, control) call must specify a different control. In my previous example I achieved that by creating the control from a template.
Oh ok, I will try this later today and let you know how it goes. Thank you.
  Reply With Quote
10/09/14, 08:41 PM   #6
Argusus
AddOn Author - Click to view addons
Join Date: Sep 2014
Posts: 120
Originally Posted by merlight View Post
ScrollListExampleMainWindow is the scroll list control. ZO_SortFilterList is a class, of which you create an instance that wraps the control and adds some children (like the header Arrow) and functionality. In order to have two lists, you need two controls to represent them. That is, each ZO_SortFilterList.New(self, control) call must specify a different control. In my previous example I achieved that by creating the control from a template.
I think i'm lost on how the ZO_SortFilterList knows which ZO_ScrollList to "wrap" and setup based on the way that the "ScrollListExample" works. Your code example makes sense but the XML version doesn't.
  Reply With Quote
10/10/14, 05:02 AM   #7
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by skobyjay View Post
I think i'm lost on how the ZO_SortFilterList knows which ZO_ScrollList to "wrap" and setup based on the way that the "ScrollListExample" works. Your code example makes sense but the XML version doesn't.
"wrap" is probably not the best word, I was thinking about "hijack" but that'd be equally confusing. I'll try to explain the relation instead, while calling it "wrap"

ZO_SortFilterList.New(class, control) -- returns an instance of class that wraps control; they call this instance manager so I'll stick to that. The control doesn't need the manager to exist, it is simply created from XML (in SLE case) or when I call CreateControlFromVirtual (in ex. above). The manager, when it is created in New, requires this control to already exist and have some children, namely "List" and "Headers". The manager wraps the "Headers" control by an instance of ZO_SortHeaderGroup, which adds sort-on-click functionality and the "Arrow" that indicates current sort key. And later it fills "List" with data rows.

Now to SLE. It defines a subclass of ZO_SortFilterList named UnitList. That's necessary because ZO_SortFilterList has some blank functions you need to override (BuildMasterList, FilterScrollList, SortScrollList). The manager (named units here) that wraps ScrollListExampleMainWindow is therefore an instance of UnitList, not just ZO_SortFilterList.
Lua Code:
  1. function UnitList:New()
  2.     local units = ZO_SortFilterList.New(self, ScrollListExampleMainWindow)
  3.     units:Initialize()
  4.     return units
  5. end
UnitList:New calls the base New with self (i.e. UnitList) as the class and ScrollListExampleMainWindow as the control argument. That's fine for an example, but bad design in a real program. It prevents anyone from creating a second instance of UnitList. The wrapped control should not be hardwired, it should either be created from a template (ex. above) or passed as an argument:
Lua Code:
  1. function UnitList:New(control)
  2.     local units = ZO_SortFilterList.New(self, control)
  3.     units:Initialize()
  4.     return units
  5. end
  Reply With Quote
10/10/14, 09:30 AM   #8
Argusus
AddOn Author - Click to view addons
Join Date: Sep 2014
Posts: 120
Originally Posted by merlight View Post
"wrap" is probably not the best word, I was thinking about "hijack" but that'd be equally confusing. I'll try to explain the relation instead, while calling it "wrap"

ZO_SortFilterList.New(class, control) -- returns an instance of class that wraps control; they call this instance manager so I'll stick to that. The control doesn't need the manager to exist, it is simply created from XML (in SLE case) or when I call CreateControlFromVirtual (in ex. above). The manager, when it is created in New, requires this control to already exist and have some children, namely "List" and "Headers". The manager wraps the "Headers" control by an instance of ZO_SortHeaderGroup, which adds sort-on-click functionality and the "Arrow" that indicates current sort key. And later it fills "List" with data rows.

Now to SLE. It defines a subclass of ZO_SortFilterList named UnitList. That's necessary because ZO_SortFilterList has some blank functions you need to override (BuildMasterList, FilterScrollList, SortScrollList). The manager (named units here) that wraps ScrollListExampleMainWindow is therefore an instance of UnitList, not just ZO_SortFilterList.
Lua Code:
  1. function UnitList:New()
  2.     local units = ZO_SortFilterList.New(self, ScrollListExampleMainWindow)
  3.     units:Initialize()
  4.     return units
  5. end
UnitList:New calls the base New with self (i.e. UnitList) as the class and ScrollListExampleMainWindow as the control argument. That's fine for an example, but bad design in a real program. It prevents anyone from creating a second instance of UnitList. The wrapped control should not be hardwired, it should either be created from a template (ex. above) or passed as an argument:
Lua Code:
  1. function UnitList:New(control)
  2.     local units = ZO_SortFilterList.New(self, control)
  3.     units:Initialize()
  4.     return units
  5. end
wow, thanks for the in-depth explanation, it makes much more sense. that is really helpful! I'll keep you posted on my progress. thanks again merlight
  Reply With Quote
10/10/14, 06:55 PM   #9
Argusus
AddOn Author - Click to view addons
Join Date: Sep 2014
Posts: 120
I found the source to my problem.

In order to have "multiple" scrolllists when defined in XML, the controls must be housed with in a unique Container parent.

Code:
<Control name="ListContainer1"> and <Control name="ListContainer2">
Then the headers name (within each Container control) MUST end with "Headers"
Code:
<Control name="$(parent)Headers">
Then the List name (within each Container control) MUST end with "List"
Code:
<Control name="$(parent)List" inherits="ZO_ScrollList">
Then as you put it, the ZO_SortFilterList can "hijack" the parent control and render itself within it.
  Reply With Quote
10/10/14, 07:20 PM   #10
Garkin
 
Garkin's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 832
Yup, there must be one child control called "List" and one called "Headers".

Lua Code:
  1. function ZO_SortFilterList:New(control)
  2.     local manager = ZO_Object.New(self)
  3.     manager.control = control
  4.     manager.list = GetControl(control, "List")
  5.     ZO_ScrollList_AddResizeOnScreenResize(manager.list)
  6.  
  7.     local headerContainer = GetControl(control, "Headers")
  8.     if(headerContainer) then
  9.         manager.sortHeaderGroup = ZO_SortHeaderGroup:New(headerContainer, true)
  10.         manager.sortHeaderGroup:RegisterCallback(ZO_SortHeaderGroup.HEADER_CLICKED, function(key, order) manager:OnSortHeaderClicked(key, order) end)
  11.         manager.sortHeaderGroup:AddHeadersFromContainer()
  12.     end
  13.  
  14.     return manager
  15. end
  Reply With Quote

ESOUI » AddOns » AddOn Help/Support » Multiple ZO_ScrollList in same window


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