Thread Tools Display Modes
03/14/15, 10:17 PM   #1
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
ZO_Tree Sort

Is there any way to sort a ZO_Tree? (I can't find one)

If not anyone have any ideas on how to get this added to my tree and keep it sorted. I'm out of ideas. The only thing I can think of is to take everything out of my organized table structure, dump all of the information into separate numerical tables, and then use ipairs(..)


I have a lot of information sorted in tables like directories. Each table may contain data and/or more tables, like this:
Warning: Spoiler


This is what I'm doing right now. It works & keeps the tree "organized" (but not sorted) like my tables, the pairs(..) function messes up the sort order.
Lua Code:
  1. local count = 0
  2. local function AddItems(tTable, parentNode)
  3.     for key, value in pairs(tTable) do
  4.         count = count + 1
  5.  
  6.         -- For testing purposes, stop after 1500 entries
  7.         if count > 1500 then break end
  8.        
  9.        if type(value) == "table" then
  10.             local nextParentNode = self.navigationTree:AddNode("Header", {["text"]=key}, parentNode, nil)
  11.             AddItems(value, nextParentNode)
  12.         else
  13.             local childNode = self.navigationTree:AddNode("NavigationEntry", {["text"]=key, ["value"]=value}, parentNode, nil)
  14.        end
  15.     end
  16. end
  17. AddItems(textures, nil)

Anyone have any ideas?

Last edited by circonian : 03/14/15 at 10:19 PM.
  Reply With Quote
03/14/15, 11:18 PM   #2
Garkin
 
Garkin's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 832
You will probably need to change structure of your tables, or make sorted table before you fill it to the tree.

Just general idea, I didn't test the code.
Lua Code:
  1. local function SortTable(tTable)
  2.     local result = {}
  3.  
  4.     for key, value in pairs(tTable) do
  5.         table.insert(result, {key, value})
  6.     end
  7.  
  8.     table.sort(result, function(a,b) return a[1] == b[1] and a[2] < b[2] or a[1] < b[1] end)
  9.  
  10.     return result
  11. end
  12.  
  13. local function AddItems(tTable, parentNode)
  14.     local sortedTable = SortTable(tTable)
  15.  
  16.     for i = 1, #tTable do
  17.         -- For testing purposes, stop after 1500 entries
  18.         if i > 1500 then break end
  19.        
  20.         if type(value) == "table" then
  21.             local nextParentNode = self.navigationTree:AddNode("Header", {["text"]=tTable[i][1]}, parentNode, nil)
  22.             AddItems(value, nextParentNode)
  23.         else
  24.             local childNode = self.navigationTree:AddNode("NavigationEntry", {["text"]=tTable[i][1], ["value"]=tTable[i][2]}, parentNode, nil)
  25.        end
  26.     end
  27. end
  28. AddItems(textures, nil)
  Reply With Quote
03/15/15, 02:38 AM   #3
Sasky
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 231
Yeah, to elaborate on Garkin's post: Lua makes 0 guarantees about the order for pairs(). You'd need to use ipairs() if you need a specific ordering, which means an array.

Here are some more structures that you could use to maintain a sorted structure at rest:
http://lua-users.org/wiki/OrderedAssociativeTable
or more to iterate in a sorted manner:
http://lua-users.org/wiki/SortedIteration
  Reply With Quote
03/15/15, 04:29 AM   #4
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
I'm was just hoping I wouldn't have to copy it into a numerical table & resort it. I had already tried it and it takes about 4 seconds to resort & populate the tree. It has about 3500 entries in it. I guess I need to find a way to restructure the tables.

Thanks Garkin & Sasky.
  Reply With Quote
03/15/15, 04:57 AM   #5
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,579
Do you really need 3500 top level entries in your tree? I don't know what exactly you plan to do, but having such a large amount of information in one level does not sound very useful to me.

edit: okay. I think I see your problem now after rereading your code.

edit2: so after reading through ZO_Tree I think it should be as easy as adding
Lua Code:
  1. if self.open then
  2.   table.sort(self.children, function(a, b) return a.data.text < b.data.text end)
  3. end
to the setupFunction of your template.
That way it will only sort the currently visible part of the tree when it is refreshed, which should be exactly what you want?

Last edited by sirinsidiator : 03/15/15 at 05:24 AM.
  Reply With Quote
03/15/15, 06:51 AM   #6
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by sirinsidiator View Post
Do you really need 3500 top level entries in your tree? I don't know what exactly you plan to do, but having such a large amount of information in one level does not sound very useful to me.

edit: okay. I think I see your problem now after rereading your code.

edit2: so after reading through ZO_Tree I think it should be as easy as adding
Lua Code:
  1. if self.open then
  2.   table.sort(self.children, function(a, b) return a.data.text < b.data.text end)
  3. end
to the setupFunction of your template.
That way it will only sort the currently visible part of the tree when it is refreshed, which should be exactly what you want?
Oh, I meant total entries. Yes, that is exactly what I wanted. I just tried again, leaving the rest of the code as-is & just adding a sort to reverse the sort order, but I still couldn't get it to work. It does sort the child table, but the items still displayed in the order they were added. Calling RefreshVisible() on the node didn't help, neither did calling Commit() on the tree again.

I also tried sorting right after I finished adding the items to the parent node, before commit ever gets called, but same results. The child tables show that they have been sorted, their order in the table changes, but it was still displaying them in the order they were added.
  Reply With Quote
03/15/15, 07:17 AM   #7
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,579
Found the problem. Inside AddChild it anchors the children and it will never update them afterwards.
In order to show the new order of your children array you need to do something like this after you sorted it:
Lua Code:
  1. local previousNode = self.children[1]
  2. previousNode:SetAnchor(TOPLEFT, self.childContainer, TOPLEFT, self.childIndent, 0)
  3. for i=2, #self.children do
  4.   local treeNode = self.children[i]
  5.   previousNode:AttachNext(treeNode)
  6.   previousNode = treeNode
  7. end
I haven't tested this myself. It might need some additional calls to
Lua Code:
  1. self:UpdateChildrenHeightsToRoot()
  2. self:UpdateCurrentChildrenHeightsToRoot()
.
  Reply With Quote
03/15/15, 06:10 PM   #8
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
sirinsidiator, I haven't tried it yet, but thats a great Idea. I never would have thought of just reanchoring/reattaching the children.
  Reply With Quote

ESOUI » Developer Discussions » Lua/XML Help » ZO_Tree Sort


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