@@ -185,8 +185,8 @@ local function MakeProfessionNodeFactory(root)
185185 label = L (isCurrent and ' Crafters' or ' Legacy Crafters' ),
186186 startCollapsed = not isCurrent ,
187187 },
188+ sorter = SortByHeaderLabel ,
188189 })
189- SetSortComparator (expansionNode , SortByHeaderLabel )
190190 db [isCurrent ] = expansionNode
191191 end
192192
@@ -208,9 +208,9 @@ local function MakeProfessionNodeFactory(root)
208208 GetLabelColor = GetCrafterNameColor ,
209209 label = CraftScan .NameAndRealmToName (char , true ),
210210 },
211+ sorter = SortByHeaderLabel ,
211212 })
212213
213- SetSortComparator (charNode , SortByHeaderLabel )
214214 charNode :Insert ({ order = 1 , bottomPadding = true })
215215 db [isCurrent ][char ] = charNode
216216 end
@@ -241,8 +241,8 @@ local function MakeProfessionNodeFactory(root)
241241 ppConfig = CraftScan .DB .characters [char ].parent_professions [profConfig .parentProfID ],
242242 LoadOptions = CraftScan .Config .LoadProfessionConfigOptions ,
243243 },
244+ sorter = false ,
244245 })
245- SetSortComparator (profNode )
246246 -- Scan_state is set as order, so 1-4 for pending/on/off/unlearned.
247247 -- Add some bottom padding by setting order higher than that - 10.
248248 profNode :Insert ({ order = 10 , bottomPadding = true })
@@ -262,8 +262,8 @@ local function MakeProfessionNodeFactory(root)
262262 label = CraftScan .RecipeStateName (recipeConfig , profConfig ),
263263 startCollapsed = true ,
264264 },
265+ sorter = SortByItemLabel ,
265266 })
266- SetSortComparator (sectionNode , SortByItemLabel )
267267 sectionNode :Insert ({ order = 1 , bottomPadding = true })
268268 profNode [recipeScanState ] = sectionNode
269269 end
@@ -321,7 +321,7 @@ local function MakeProfessionNodeFactory(root)
321321 -- it, there's a bit of a screen lock up as the tree is updated, so we
322322 -- time slice that into small chunks so the tree updates in real time
323323 -- for the user to see instead of freezing the screen.
324- local perFrame = existingRecipeIDs and 5 or 10000000
324+ local perFrame = existingRecipeIDs and 5 or 2000000
325325
326326 if not profConfig .recipes then
327327 if onFinished then
@@ -535,39 +535,49 @@ function CraftScanConfigPageMixin:ToggleMenu()
535535 self :SetMenuCollapsed (not self .isMenuCollapsed )
536536end
537537
538- function CraftScanConfigPageMixin :SelectRecipe (char , profID , recipeID , retryCount )
539- retryCount = retryCount or 0
538+ function CraftScanConfigPageMixin :SelectRecipe (char , profID , recipeID , attachButton )
539+ local menu = self . Menu
540540
541- self :Show ()
541+ local function OnMenuInitialized ()
542+ if ProfessionsFrame .CraftingPage .SchematicForm :IsShown () then
543+ self :SetMenuCollapsed (true )
544+ self :AnchorToProfessionPage ()
545+ end
542546
543- if ProfessionsFrame .CraftingPage .SchematicForm :IsShown () then
544- self :SetMenuCollapsed (true )
545- self :AnchorToProfessionPage ()
547+ local dataProvider = menu .dataProvider
548+
549+ -- Find the tree node containing what we need.
550+ local node = dataProvider :FindElementDataByPredicate (function (node )
551+ local data = node :GetData ()
552+ return data .configInfo
553+ and data .configInfo .recipeID
554+ and data .configInfo .recipeID == recipeID
555+ and data .configInfo .char == char
556+ and data .configInfo .profID == profID
557+ end , TreeDataProviderConstants .IncludeCollapsed )
558+
559+ if node then
560+ menu .ExpandToNode (dataProvider :GetRootNode (), node :GetData ().configInfo )
561+ menu .selectionBehavior :SelectElementData (node )
562+ dataProvider :Invalidate ()
563+ menu .ScrollBox :ScrollToElementData (node )
564+ end
546565 end
547566
548- local menu = self .Menu
549- local dataProvider = menu .dataProvider
550-
551- -- Find the tree node containing what we need.
552- local node = dataProvider :FindElementDataByPredicate (function (node )
553- local data = node :GetData ()
554- return data .configInfo
555- and data .configInfo .recipeID
556- and data .configInfo .recipeID == recipeID
557- and data .configInfo .char == char
558- and data .configInfo .profID == profID
559- end , TreeDataProviderConstants .IncludeCollapsed )
560-
561- if node then
562- menu .ExpandToNode (dataProvider :GetRootNode (), node :GetData ().configInfo )
563- menu .selectionBehavior :SelectElementData (node )
564- dataProvider :Invalidate ()
565- menu .ScrollBox :ScrollToElementData (node )
566- elseif retryCount < 50 then
567- -- Fail / Retry: The recipe isn't loaded yet.
568- C_Timer .After (0.1 , function ()
569- self :SelectRecipe (char , profID , recipeID , retryCount + 1 )
570- end )
567+ if self :IsShown () then
568+ OnMenuInitialized ()
569+ else
570+ if attachButton then
571+ attachButton :AttachedMenuLoading ()
572+ end
573+ menu .onMenuInitialized = function ()
574+ OnMenuInitialized ()
575+ self :Show ()
576+ if attachButton then
577+ attachButton :AttachedMenuLoadComplete ()
578+ end
579+ end
580+ menu :InitMenu ()
571581 end
572582end
573583
@@ -724,10 +734,16 @@ function CraftScanConfigMenuMixin:OnLoad()
724734 if event == ' NEW_RECIPE_LEARNED' then
725735 local recipeID , recipeLevel , baseRecipeID = ...
726736
727- if issecretvalue (recipeID ) then return end
737+ if issecretvalue (recipeID ) then
738+ return
739+ end
728740
729741 local profInfo = C_TradeSkillUI .GetProfessionInfoByRecipeID (recipeID )
730- if not profInfo .isPrimaryProfession or not profInfo .parentProfessionID or not CraftScan .DB .characters [char ] then
742+ if
743+ not profInfo .isPrimaryProfession
744+ or not profInfo .parentProfessionID
745+ or not CraftScan .DB .characters [char ]
746+ then
731747 return
732748 end
733749 local char = CraftScan .GetPlayerName (true )
@@ -773,19 +789,30 @@ end
773789CraftScan .Config = {}
774790CraftScan .Config .OnConfigChange = OnConfigChange
775791
792+ function CraftScanConfigMenuMixin :OnMenuInitialized ()
793+ if self .onMenuInitialized then
794+ self .onMenuInitialized ()
795+ self .onMenuInitialized = nil
796+ end
797+ end
798+
776799function CraftScanConfigMenuMixin :OnShow ()
800+ self :InitMenu ()
801+ end
802+
803+ function CraftScanConfigMenuMixin :InitMenu ()
777804 if menuInitialized then
805+ self :OnMenuInitialized ()
778806 return
779807 end
808+
780809 menuInitialized = true
781810
782811 local dataProvider = CreateTreeDataProvider ()
783812 self .dataProvider = dataProvider
784813
785814 local node = dataProvider :GetRootNode ()
786815
787- SetSortComparator (node , SortByHeaderLabel )
788-
789816 local generalNode = node :Insert ({
790817 order = 0 ,
791818 configInfo = {
@@ -809,6 +836,18 @@ function CraftScanConfigMenuMixin:OnShow()
809836 local excludeCollapsed = false
810837 dataProvider :ForEach (function (node )
811838 local elementData = node :GetData ()
839+
840+ -- Now that the full tree is populated, apply the sorter for a
841+ -- single n*log(n) sort instead of the original n*n*log(n) we got
842+ -- from applying the sorter before inserting children.
843+ if elementData .sorter ~= nil then
844+ if elementData .sorter then
845+ SetSortComparator (node , elementData .sorter )
846+ else
847+ SetSortComparator (node )
848+ end
849+ elementData .sorter = nil
850+ end
812851 if elementData .headerInfo and elementData .headerInfo .startCollapsed then
813852 node :SetCollapsed (true )
814853
@@ -821,17 +860,33 @@ function CraftScanConfigMenuMixin:OnShow()
821860 end , excludeCollapsed )
822861 end
823862
863+ -- Wait until we have fully populated the tree to render it. Before
864+ -- rendering, we collapse almost all the nodes so we only display the
865+ -- current expansion's professions
866+ local waitGroup = CraftScan .WaitGroup (function ()
867+ CollapseTree ()
868+ SetSortComparator (node , SortByHeaderLabel )
869+ self .ScrollBox :SetDataProvider (dataProvider , ScrollBoxConstants .RetainScrollPosition )
870+ self .selectionBehavior :SelectElementData (generalNode )
871+ self .ScrollBox :ScrollToElementData (generalNode )
872+ self .Spinner :SetShown (false )
873+ self :OnMenuInitialized ()
874+ end )
875+
876+ local OnProfessionLoadComplete = function ()
877+ waitGroup :Done ()
878+ end
879+
880+ self .Spinner :SetShown (true )
824881 self .GetRecipeParentNode , self .PopulateProfessionNode , self .UpdateProfessionNode , self .RemoveMissingProfessionNodes , self .ExpandToNode =
825882 MakeProfessionNodeFactory (node )
826883 for char , charConfig in pairs (CraftScan .DB .characters ) do
827884 for profID , profConfig in pairs (charConfig .professions ) do
828- self .PopulateProfessionNode (char , profID , profConfig , nil , CollapseTree )
885+ waitGroup :Add ()
886+ self .PopulateProfessionNode (char , profID , profConfig , nil , OnProfessionLoadComplete )
829887 end
830888 end
831-
832- self .ScrollBox :SetDataProvider (dataProvider , ScrollBoxConstants .RetainScrollPosition )
833- self .selectionBehavior :SelectElementData (generalNode )
834- self .ScrollBox :ScrollToElementData (generalNode )
889+ waitGroup :Close ()
835890end
836891
837892CraftScanConfigMenuHeaderMixin = {}
924979
925980function CraftScan .Config .OnRecipeScanStateChange (configInfo , skipReload )
926981 -- If the tree hasn't initialized the configInfo yet, nothing to do.
927- if not configInfo .treeNode then return end
982+ if not configInfo .treeNode then
983+ return
984+ end
928985
929986 local menu = CraftScanConfigPage .Menu
930987 local newParent = menu .GetRecipeParentNode (
0 commit comments