06/13/21, 03:52 PM | #1 |
|
How to two columns in ZO_ScrollList?
Hi there,
I am very new (2 days) to the LUA AddOn development. I want to make an addon which shows me the cloth related materials and how much i have in stock. Its for my old brain to know what I still have to buy for my crafting cause i am low on stockitems. So far i have managed this (see Attachment). A lot of examples and reading and try and error... Last thing i want to do: How can i get the data in 2 columns? At the moment i add the Data via a DataType from an array to the xml in a ZO_ScrollList control. I use a simple string concatenate Any help would be very appreciated! Relevant parts from the lua Code:
function Crafty.CreateScrollListDataType() d("Crafty: CreateScrollListDataType") local control = CraftyListList local typeId = 1 local templateName = "ZO_SelectableLabel" local height = 25 -- height of the row, not the window local setupFunction = Crafty.LayoutRow local hideCallback = nil local dataTypeSelectSound = nil local resetControlCallback = nil local selectTemplate = "ZO_ThinListHighlight" local selectCallback = Crafty.OnRowSelect ZO_ScrollList_AddDataType(control, typeId, templateName, height, setupFunction, hideCallback, dataTypeSelectSound, resetControlCallback) --ZO_ScrollList_EnableSelection(control, selectTemplate, selectCallback) end function Crafty.Populate() d("Crafty: Populate") local stock = {} local stockcounter = 0 for index, data in pairs(SHARED_INVENTORY.bagCache[BAG_VIRTUAL]) do if data ~= nil then if GetItemCraftingInfo(BAG_VIRTUAL,data.slotIndex) == 2 then stockcounter = stockcounter + 1 stock[stockcounter] = { link = GetItemLink(BAG_VIRTUAL,data.slotIndex), name = GetItemName(BAG_VIRTUAL,data.slotIndex), amount = GetSlotStackSize(BAG_VIRTUAL,data.slotIndex), cinfo = GetItemCraftingInfo(BAG_VIRTUAL,data.slotIndex) } end end end return stock end function Crafty.UpdateScrollList(control, data, rowType) d("Crafty: UpdateScrollList") local dataCopy = ZO_DeepTableCopy(data) local dataList = ZO_ScrollList_GetDataList(control) ZO_ScrollList_Clear(control) for key, value in ipairs(dataCopy) do local entry = ZO_ScrollList_CreateDataEntry(rowType, value) table.insert(dataList, entry) end table.sort(dataList, function(a,b) return a.data.name < b.data.name end) ZO_ScrollList_Commit(control) end function Crafty.LayoutRow(rowControl, data, scrollList) --d("Crafty: LayoutRow") rowControl:SetFont("ZoFontWinH4") rowControl:SetMaxLineCount(1) rowControl:SetText(data.link.." / "..data.amount) rowControl:SetHandler("OnMouseUp", function() ZO_ScrollList_MouseClick(scrollList, rowControl) end) end Code:
<GuiXml> <Controls> <TopLevelControl name="CraftyList" hidden="false" mouseEnabled="true" movable="true" clampedToScreen="true"> <Anchor point="BOTTOM" relativeTo="GuiRoot" relativePoint="BOTTOM" offsetX="0" offsetY="-128"/> <OnMoveStop> Crafty.OnIndicatorMoveStop() </OnMoveStop> <Dimensions x="300" y="400" /> <Controls> <Backdrop name="$(parent)BG" inherits="ZO_ThinBackdrop" /> <Button name="$(parent)ButtonClose" inherits="ZO_ButtonBehaviorClickSound"> <Dimensions x="30" y="30" /> <Anchor point="TOPRIGHT" relativeTo="$(parent)" relativePoint="TOPRIGHT" offsetX="5" offsetY="5" /> <Textures normal="EsoUI/Art/Buttons/closebutton_up.dds" pressed="EsoUI/Art/Buttons/closebutton_down.dds" mouseOver="EsoUI/Art/Buttons/closebutton_mouseover.dds" disabled="EsoUI/Art/Buttons/closebutton_disabled.dds"/> <OnClicked> Crafty.UpdateScrollList() </OnClicked> </Button> <Button name="$(parent)ButtonRrefresh" inherits="ZO_ButtonBehaviorClickSound"> <Dimensions x="30" y="30" /> <Anchor point="TOPRIGHT" relativeTo="$(parent)ButtonClose" relativePoint="TOPLEFT" offsetX="-5" offsetY="-2" /> <Textures normal="EsoUI/Art/Buttons/downarrow_up.dds" pressed="EsoUI/Art/Buttons/downarrow_down.dds" mouseOver="EsoUI/Art/Buttons/downarrow_over.dds" disabled="EsoUI/Art/Buttons/downarrow_disabled.dds"/> <OnClicked> Crafty.UpdateScrollList() </OnClicked> </Button> <Label name="$(parent)Title" font="ZoFontGameLargeBold" color="CFDCBD" wrapMode="ELLIPSIS" verticalAlignment="CENTER" text="STOCKLIST"> <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="10" offsetY="10"/> </Label> <Label name="$(parent)Heading" font="ZoFontGameLargeBold" color="CFDCBD" wrapMode="ELLIPSIS" verticalAlignment="CENTER" text="Itemname / Stockamount"> <Anchor point="TOPLEFT" relativeTo="$(parent)Title" relativePoint="BOTTOMLEFT" offsetX="0" offsetY="10"/> </Label> <Texture name="$(parent)Divider" textureFile="/esoui/art/miscellaneous/horizontaldivider.dds" tier="HIGH"> <Dimensions x="300" y="4"/> <Anchor point="TOPLEFT" relativeTo="$(parent)Heading" relativePoint="BOTTOMLEFT" offsetY="10" /> </Texture> <Control name="$(parent)List" inherits="ZO_ScrollList"> <Anchor point="TOPLEFT" relativeTo="$(parent)Divider" relativePoint="BOTTOMLEFT" offsetY="10" /> <Anchor point="BOTTOMRIGHT" offsetX="-10" offsetY="-10" /> </Control> </Controls> </TopLevelControl> </Controls> </GuiXml> |
06/14/21, 01:46 AM | #2 |
I'm not sure that the normal ZO_ScrollList is defined to have more than 1 column but the ZO_SortFilterList got it.
But it's more complicated. The basic info you need is that the function here ZO_ScrollList_AddDataType(control, typeId, templateName uses the templateName as 3rd parameter. e.g. templateName = "MyUniqueAddonsXMLRowTemplateName" You need to define the templatename as XML "virtual" row control like that: Code:
<GuiXml> <Controls> <!-- Virtual row for the ZO_SortList of this widget --> <Label name="MyUniqueAddonsXMLRowTemplateName" mouseEnabled="true" virtual="true" color="INTERFACE_COLOR_TYPE_TEXT_COLORS:INTERFACE_TEXT_COLOR_NORMAL"> <OnInitialized> ZO_SelectableLabel_OnInitialized(self) </OnInitialized> <OnMouseEnter> ZO_SelectableLabel_OnMouseEnter(self) </OnMouseEnter> <OnMouseExit> ZO_SelectableLabel_OnMouseExit(self) </OnMouseExit> <OnDragStart> LAM2_orderlistbox_widget_OnDragStart(self, button) </OnDragStart> <OnReceiveDrag> LAM2_orderlistbox_widget_OnReceiveDrag(self, button) </OnReceiveDrag> </Label> In the scroll list you need to use the data table of the row then to populate the data table's column to the XML's column. This can be done via the setupFunction e.g. or other functions like ZO_SortList:BuildMasterList (I think this was the name). If you change your XML file to <Control name="$(parent)List" inherits="ZO_SortFilterList"> you must add a SortHeader control to it as well! And define the row template etc. like described abobe. This should work then for sure. Examples of the ZO_SortFilterList can be found in ZOs code or other addons like WishList e.g. The WishList XML got some comments which might help. The lua code is in file WL_window.lua then. I'm using 1 ZO_SortFilterLists there which just changes the visible columns and populates other data for 3 different output tabs (add items, wishlist and history). If you need further assistance there feel free to ask. Additional info about the ZO_SortList etc. can be found here, including the function call order of the ZO_SortFilterList: https://wiki.esoui.com/How_to..._do_...templated_rows Last edited by Baertram : 06/14/21 at 01:53 AM. |
|
06/14/21, 05:06 AM | #3 |
|
Thanks a lot!
Damn I did not find this tutorial. I will give it a try later today. Seams that these are the droids I am looking for! |
06/14/21, 05:33 AM | #4 |
Maybe this library helps as well:
https://www.esoui.com/downloads/info1151-LibScroll.html |
|
06/14/21, 01:20 PM | #5 |
|
Ok.. I am officially lost.. I found other examples which all only show a part of the code from which I cant adapt to my code. There are no examples which you can use to learn and to understand. Copy a part from an example, insert it in own code, errors. bugfixing for hours.
And I also dont want to reengineer other complete addons for the things i need to know. This takes forever. The ESO function lua documentation is really bad And I used to be a java developer. I often read "look in the ZO Code how they did it".. this is the way? I really appreciate the help here and normally the starting points in the postings are enaugh to go on.. but with this bad ZO documentation... its more than frustrating. Dont know how you guys make it. |
06/14/21, 03:01 PM | #6 | ||
That's the way. We are glad we even got the source and ESOUDocumentation_Pxx.txt API function files
Basically you need the following as I had written above: https://www.esoui.com/downloads/info...stExample.html -> To understand the basic sort list of ZO_SortList Wiki: https://wiki.esoui.com/How_to..._do_...templated_rows -> To see what else is needed for the ZO_SortFilterList. It inherits from ZO_SortList but you need to use some other code like the XML providing the List and SortHeader control containers. And the functions ZO_SortFilterList:RefreshData() => BuildMasterList() => FilterScrollList() => SortScrollList() => CommitScrollList() The XML, as shown in the Wiki examples, provide the virtual and non virtual controls for the row -> contains the column labels. In your SetupFunction of the sortFilterList, which you specify at the ZO_ScrollList_AddDataType parameters, you define what data is passed to what column (you need to get the columns via e.g. rowControl:GetNamedChild("myColumNameFromXML"). Have a look at maybe LibShifterBox and search for ZO_ScrollList_AddDataType . Check the XML file and the lua file, it's a library providing 2 ZO_SortFilterLists (left and right) with only 1 column. Or at WishList, it provides 1 ZO_SortFilterList providing multiple columns. Or download the ESOUI source code https://www.esoui.com/downloads/info...ourcecode.html and search for ZO_SortFilterList and you'll get a lot of examples. e.g. the FriendsList Keyboard. The function here contains the init of the ZO_SortFilterList (they use an inherited class named "ZO_SocialListKeyboard" there which inherits from ZO_SortFilterList): ZO_KeyboardFriendsListManager:Initialize(control, rowTemplate) ZO_ScrollList_AddDataType(self.list, FRIEND_DATA, rowTemplate, 30, function(control, data) self:SetupRow(control, data) end) ZO_ScrollList_EnableHighlight(self.list, "ZO_ThinListHighlight") AddDataType provides the XML template via param rowTemplate. The param is given via this function, which is called from the XML code of the keyboard stuff <OnInitialization> Lua Code:
This line here calls the :New function: FRIENDS_LIST = ZO_KeyboardFriendsListManager:New(self, rowTemplate) The template name would be e.g. "ZO_FriendsListRow" which you are able to find in the XML file: friendslist_keyboard.xml Code:
<Label name="ZO_FriendsListRowLabel" font="ZoFontGame" wrapMode="ELLIPSIS" virtual="true"/> <Control name="ZO_FriendsListRow" mouseEnabled="true" virtual="true"> <Dimensions y="30"/> <OnMouseEnter> ZO_FriendsListRow_OnMouseEnter(self) </OnMouseEnter> <OnMouseExit> ZO_FriendsListRow_OnMouseExit(self) </OnMouseExit> <OnMouseUp> ZO_FriendsListRow_OnMouseUp(self, button, upInside) </OnMouseUp> <Controls> <Texture name="$(parent)BG" inherits="ZO_ThinListBgStrip" /> <Texture name="$(parent)StatusIcon" layer="OVERLAY" mouseEnabled="true"> <Anchor point="LEFT"/> <Dimensions x="32" y="32"/> <OnMouseEnter> ZO_FriendsListRowStatus_OnMouseEnter(self) </OnMouseEnter> <OnMouseExit> ZO_FriendsListRowStatus_OnMouseExit(self) </OnMouseExit> </Texture> <Texture name="$(parent)AllianceIcon" mouseEnabled="true" layer="OVERLAY"> <Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$(parent)StatusIcon"/> <Dimensions x="32" y="32"/> <OnMouseEnter> ZO_FriendsListRowAlliance_OnMouseEnter(self) </OnMouseEnter> <OnMouseExit> ZO_FriendsListRowAlliance_OnMouseExit(self) </OnMouseExit> </Texture> <Label name="$(parent)DisplayName" inherits="ZO_FriendsListRowLabel" verticalAlignment="CENTER" mouseEnabled="true"> <Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$(parent)AllianceIcon" offsetX="25"/> <Dimensions x="225" y="30"/> <OnMouseEnter> ZO_FriendsListRowDisplayName_OnMouseEnter(self) </OnMouseEnter> <OnMouseExit> ZO_FriendsListRowDisplayName_OnMouseExit(self) </OnMouseExit> <OnMouseUp> ZO_FriendsListRow_OnMouseUp(self:GetParent(), button, upInside) </OnMouseUp> </Label> <Label name="$(parent)Zone" inherits="ZO_FriendsListRowLabel"> <Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$(parent)DisplayName" offsetX="18"/> <Dimensions x="290" y="20"/> </Label> <Texture name="$(parent)ClassIcon" mouseEnabled="true" layer="OVERLAY"> <Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$(parent)Zone" offsetX="28"/> <Dimensions x="32" y="32"/> <OnMouseEnter> ZO_FriendsListRowClass_OnMouseEnter(self) </OnMouseEnter> <OnMouseExit> ZO_FriendsListRowClass_OnMouseExit(self) </OnMouseExit> </Texture> <Texture name="$(parent)Champion" mouseEnabled="true" layer="OVERLAY"> <Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$(parent)ClassIcon" offsetX="20" offsetY="2"/> <Dimensions x="22" y="22"/> <OnMouseEnter> ZO_FriendsListRowChampion_OnMouseEnter(self) </OnMouseEnter> <OnMouseExit> ZO_FriendsListRowChampion_OnMouseExit(self) </OnMouseExit> </Texture> <Label name="$(parent)Level" inherits="ZO_FriendsListRowLabel" horizontalAlignment="CENTER" verticalAlignment="CENTER"> <Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$(parent)ClassIcon" offsetX="39"/> <Dimensions x="45" y="20"/> </Label> <Button name="$(parent)Note"> <Textures normal="EsoUI/Art/Contacts/social_note_up.dds" pressed="EsoUI/Art/Contacts/social_note_down.dds" mouseOver="EsoUI/Art/Contacts/social_note_over.dds" /> <Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$(parent)Level" offsetX="18"/> <Dimensions x="32" y="32"/> <OnMouseEnter> ZO_FriendsListRowNote_OnMouseEnter(self) </OnMouseEnter> <OnMouseExit> ZO_FriendsListRowNote_OnMouseExit(self) </OnMouseExit> <OnClicked> ZO_FriendsListRowNote_OnClicked(self) </OnClicked> </Button> </Controls> </Control> Then you got different labels in there which define the columns, and which inherit from the virtual label "ZO_FriendsListRowLabel". Hope this makes clear how to define the XML now. Also needed, like you can find in the same file, and mentioned in the Wiki: The sortheader container in the XML Code:
<Control name="ZO_FriendsListHeaders" mouseEnabled="true" virtual="true"> Code:
<!-- Headers control added dynamically based on above templates --> <Control name="$(parent)List" inherits="ZO_ScrollList" /> ZO_FriendsListRow -> ZO_FriendsListHeaders ZO_FriendsListRow_Heron -> ZO_FriendsListRow_Heron -> See function ZO_FriendsList_OnInitialized(self) above -> e.g. headersControl = CreateControlFromVirtual("$(parent)Headers", self, "ZO_FriendsListHeaders") After that back to the lua code: Every :New function normally calls an Initilaized function internally. So FRIENDS_LIST = ZO_KeyboardFriendsListManager:New(self, rowTemplate) -> ZO_KeyboardFriendsListManager:New(...) calls ZO_KeyboardFriendsListManager:Initialize(...) And there we get to the functions I had named above already: ZO_ScrollList_AddDataType(self.list, FRIEND_DATA, rowTemplate, 30, function(control, data) self:SetupRow(control, data) end) Code:
--Adds a new control type for the list to handle. It must maintain a consistent size. --@typeId - A unique identifier to give to CreateDataEntry when you want to add an element of this type. --@templateName - The name of the virtual control template that will be used to hold this data --@height - The control height --@setupCallback - The function that will be called when a control of this type becomes visible. Signature: setupCallback(control, data) --@dataTypeSelectSound - An optional sound to play when a row of this data type is selected. --@resetControlCallback - An optional callback when the datatype control gets reset. function ZO_ScrollList_AddDataType(self, typeId, templateName, height, setupCallback, hideCallback, dataTypeSelectSound, resetControlCallback) Code:
--@highlightTemplate- The name of the virtual control template that will be used to show the highlight --@highlightCallback- The callback function run as an entry is highlighted --@overrideEndAlpha-I don't know but sounds like an SetAlpha override for the row. Try it (values should be 0 to 1 in 0.01 or 0.1 steps) function ZO_ScrollList_EnableHighlight(self, highlightTemplate, highlightCallback, overrideEndAlpha) The sort function is used as the sort headers are used. The search box is deinfed in teh XML and can be used to filter the list data. self:SetupRow(control, data) is the setupCallback function for each row! Search for ZO_KeyboardFriendsListManager:SetupRow(control, data) and you'll find it in the source. It calls the default setuprow func of the ZO_SortFilterLists ZO_SortFilterList.SetupRow(self, control, data) And a custom setup function of the friends list: FRIENDS_LIST_MANAGER:SetupEntry(control, data) As FRIENDS_LIST_MANAGER = ZO_FriendsList:New() -> Search in file friendslist_shared.lua where the ZO_FriendsList is defined! -> Search for SetupEntry and you'll find: Lua Code:
Here you'll find, as I tried to describe above, how the columns are determined via the :GetNamedChild function of the rowControl, e.g. local noteControl = ccontrol:GetNamedChild("Note") -> Note is the <Button name="$(parent)Note"> from the XML row template in e.g. "ZO_FriendsListRow", see above! data is the table that contans the data of the row. Each row got 1 data entry, containing sub entries you need to specify in the BuildMasterList function e.g. See same file: Lua Code:
self.masterList is the table containing your list data entries. local data = self:CreateFriendData(i, displayName, note, status) -> Creates the data entry table with it's entries needed, like the status, the note text and so on. ZO_SocialList_SetUpOnlineData(data, online, secsSinceLogoff) -> is just a local helper function to update some values in the data table self.masterList[i] = data -> The masterlist get's a new entry. Remember: The default order of the functions called is: ZO_SortFilterList:RefreshData() => BuildMasterList() => FilterScrollList() => SortScrollList() => CommitScrollList() After the masterlist was build the FilterScrollList function would be called to filter the masterlist. After that the SortSrollList function sorts them according to the sortheaders chosen. And CommtiScrollList updates the visual values then in the list according to the sorted masterlist entries. The SetupRow callback function then provides the data.note etc. values to the appropriate chosen XML label/button/texture controls. I hope this clears it up for you now and you are able to build an example I'd start with the example ZO_SortList at the top and "enhance" it to use a ZO_SortFilterList instead, with an own simple 2 columns XML template. Just re-use the given collectibles/pets from the example and add the number of the collectible as plain tetx e.g. for the start. If you got that working provide me the example addon please and I'll have alook if one can release it as another ZO_SortFilterList example here at esoui, with some comments, so that the missing ZOs documentation again will be done by us Last edited by Baertram : 06/14/21 at 03:55 PM. |
|||
06/14/21, 05:51 PM | #7 |
|
phew, thanks.
I am still on it (nearly 2am! have work tomorrow) and I try working with the old version from ScrollListExample. The one with the pets, only works with one row. This I accomplished too (two days ago) Currently i struggle with the xml for the row with one control and two labels and with the data. Rest of the xml with the header and stuff is working. Last reloadui ESO crashed I am getting there... the hard way... Yes i will definitly provide it as an example. I allready have nightmares like.... /...r...e...l...o..a..d...u....i... and again and again |
06/14/21, 06:15 PM | #8 |
|
2.12 AM
ITS WORKING! Just using ScrollList. Need to fix some width data... later this day |
06/15/21, 01:49 AM | #9 |
yw and congratulations, glad it works now
It took me quite a time to understand the methods and stuff as well. But praticing is the best way to learn it btw: If you use inspection helper tools like merTorchbug updated you only need to type /rl or specify a keybind for the reloadui Last edited by Baertram : 06/15/21 at 04:58 AM. |
|
06/17/21, 11:06 AM | #10 |
|
Hi there,
I just wanted to let you know that the development is going on great! Take a look at the screenshot. You can fill the watchlist from a stocklist (with categories) and you can have 3 watchlists The stocklist can be sticky to the watchlist. Also you have some settings and keybindings. Thanks a again for the help! |
06/17/21, 11:12 AM | #11 |
Great, if you got a simple 1 list example (your version from 2021-06-15, 1am e.g.) I could re-use for an example addon, just send me the code (or put it to GitHub if you use it).
I'd be glad to add some comments and release it some day then, same as the other ZO_SortList example was released. If you want to do it by your own, go ahead as well Just please link it at the Wiki then too, next the others: https://wiki.esoui.com/How_to..._do_UI_element_X -> below "ZO_SortFilterList is another ZO_ScrollList inherited control where you need to define a "List" in your XML..." |
|
06/18/21, 08:13 AM | #12 |
|
Hi there,
I will add an example as soon as I understand everything to describe it properly and to be sure not to have done something stupid I now have a stable betaversion which had some testing and everthing looks nice. If anyone want to take a look in the undocumented code its on github: https://github.com/rp12439/crafty |
06/18/21, 04:11 PM | #13 |
|
Finally published the addon:
https://www.esoui.com/downloads/info...rofession.html Still working an example |
ESOUI » Developer Discussions » Lua/XML Help » How to two columns in ZO_ScrollList? |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Linear Mode |
Switch to Hybrid Mode |
Switch to Threaded Mode |
|
|