@@ -66,6 +66,8 @@ AceConfigCmd:CreateChatCommand('cs', 'CraftScan')
6666
6767table.insert (UISpecialFrames , ' CraftScanConfigPage' )
6868
69+ local menuInitialized = false
70+
6971local function IsEmptyNode (node )
7072 for _ , child in ipairs (node :GetNodes ()) do
7173 if child .data and (child .data .configInfo or child .data .headerInfo ) then
@@ -142,19 +144,6 @@ local function GetScanStateDisplayOrder(recipeConfig, profConfig)
142144 end
143145end
144146
145- function CraftScan .SaveConcentrationData ()
146- local skillLineID = C_TradeSkillUI .GetProfessionChildSkillLineID ()
147- if C_ProfSpecs .SkillLineHasSpecialization (skillLineID ) then
148- local currencyID = C_TradeSkillUI .GetConcentrationCurrencyID (skillLineID )
149- local concentrationData = CraftScan .ConcentrationData (currencyID )
150- local char = CraftScan .GetPlayerName (true )
151- local profConfig = CraftScan .DB .characters [char ].professions [skillLineID ]
152- if profConfig then
153- profConfig .concentration = concentrationData :Serialize ()
154- end
155- end
156- end
157-
158147local function SortByHeaderLabel (lhs , rhs )
159148 return strcmputf8i (lhs .data .headerInfo .label , rhs .data .headerInfo .label ) < 0
160149end
@@ -190,6 +179,7 @@ local function MakeProfessionNodeFactory(root)
190179 local isCurrent = CraftScan .Utils .IsCurrentExpansion (profID )
191180 if not db [isCurrent ] then
192181 local expansionNode = root :Insert ({
182+ parentKey = isCurrent ,
193183 order = isCurrent and 3 or 4 ,
194184 headerInfo = {
195185 label = L (isCurrent and ' Crafters' or ' Legacy Crafters' ),
@@ -453,15 +443,106 @@ function CraftScanConfigPageMixin:ToggleVisibility()
453443 if self :IsShown () then
454444 self :Hide ()
455445 else
446+ self :SetMenuCollapsed (false )
456447 self :Show ()
457448 end
458449end
459450
460- function CraftScanConfigPageMixin :SelectRecipe (char , profID , recipeID )
451+ function CraftScanConfigPageMixin :AnchorToProfessionPage ()
452+ local profFrame = _G [' ProfessionsFrame' ]
453+ if not profFrame or not profFrame :IsShown () then
454+ return
455+ end
456+
457+ self :ClearAllPoints ()
458+ if self .isMenuCollapsed then
459+ self :SetPoint (' TOPLEFT' , profFrame , ' TOPRIGHT' , 0 , 0 )
460+ self :SetPoint (' BOTTOMLEFT' , profFrame , ' BOTTOMRIGHT' , 0 , 0 )
461+ else
462+ local menuWidth = self .Menu :GetWidth ()
463+ self :SetPoint (' TOPLEFT' , profFrame , ' TOPRIGHT' , - menuWidth , 0 )
464+ self :SetPoint (' BOTTOMLEFT' , profFrame , ' BOTTOMRIGHT' , - menuWidth , 0 )
465+ end
466+
467+ -- Ensure we stay behind Blizzard
468+ self :SetFrameLevel (math.max (0 , profFrame :GetFrameLevel () - 1 ))
469+ profFrame :Raise ()
470+ end
471+
472+ function CraftScanConfigPageMixin :ResizeOptionsPanel (collapsed , activeOptions )
473+ local width = 1105
474+ if collapsed then
475+ if activeOptions then
476+ width = activeOptions :GetWidth ()
477+ else
478+ width = width - 350
479+ end
480+ end
481+ self :SetWidth (width )
482+ end
483+
484+ function CraftScanConfigPageMixin :SetMenuCollapsed (collapsed )
485+ if self .isMenuCollapsed == collapsed then
486+ return
487+ end
488+
489+ self .isMenuCollapsed = collapsed
490+ self .Menu :SetShown (not collapsed )
491+
492+ if self .Menu .activeOptions and self .Menu .activeOptions .Layout then
493+ self .Menu .activeOptions :Layout (collapsed )
494+ end
495+
496+ self :ResizeOptionsPanel (collapsed , self .Menu .activeOptions )
497+
498+ -- Update the Options panel anchoring
499+ self .Options :ClearAllPoints ()
500+ if collapsed then
501+ -- COLLAPSED: Snap the options to the LEFT edge of the whole frame
502+ self .Options :SetPoint (' TOPLEFT' , self , ' TOPLEFT' , 4 , - 62 )
503+ self .Options :SetPoint (' BOTTOMRIGHT' , self , ' BOTTOMRIGHT' , - 4 , 4 )
504+ else
505+ -- EXPANDED: Snap it back to the RIGHT side of the Menu
506+ self .Options :SetPoint (' TOPLEFT' , self .Menu , ' TOPRIGHT' , 0 , 0 )
507+ self .Options :SetPoint (' BOTTOMRIGHT' , self , ' BOTTOMRIGHT' , 0 , 4 )
508+ end
509+
510+ -- 3. Update the button's internal state so the arrow points the right way
511+ if collapsed then
512+ self .MaximizeMinimize :Minimize ()
513+ else
514+ self .MaximizeMinimize :Maximize ()
515+ end
516+
517+ if collapsed and ProfessionsFrame :IsShown () then
518+ self :AnchorToProfessionPage ()
519+ end
520+ end
521+
522+ CraftScan .Events :Register (' ACTIVE_OPTION_UPDATED' , function (activeOptions )
523+ local page = CraftScanConfigPage
524+ page :ResizeOptionsPanel (page .isMenuCollapsed , activeOptions )
525+ end )
526+
527+ function CraftScanConfigPageMixin :ToggleMenu ()
528+ self :SetMenuCollapsed (not self .isMenuCollapsed )
529+ end
530+
531+ function CraftScanConfigPageMixin :SelectRecipe (char , profID , recipeID , retryCount )
532+ retryCount = retryCount or 0
533+
534+ self :Show ()
535+
536+ if ProfessionsFrame .CraftingPage .SchematicForm :IsShown () then
537+ self :SetMenuCollapsed (true )
538+ self :AnchorToProfessionPage ()
539+ end
540+
461541 local menu = self .Menu
542+ local dataProvider = menu .dataProvider
462543
463544 -- Find the tree node containing what we need.
464- local node = self . Menu . dataProvider :FindElementDataByPredicate (function (node )
545+ local node = dataProvider :FindElementDataByPredicate (function (node )
465546 local data = node :GetData ()
466547 return data .configInfo
467548 and data .configInfo .recipeID
@@ -471,10 +552,15 @@ function CraftScanConfigPageMixin:SelectRecipe(char, profID, recipeID)
471552 end , TreeDataProviderConstants .IncludeCollapsed )
472553
473554 if node then
474- menu .ExpandToNode (menu . dataProvider :GetRootNode (), node :GetData ().configInfo )
555+ menu .ExpandToNode (dataProvider :GetRootNode (), node :GetData ().configInfo )
475556 menu .selectionBehavior :SelectElementData (node )
476- menu . dataProvider :Invalidate ()
557+ dataProvider :Invalidate ()
477558 menu .ScrollBox :ScrollToElementData (node )
559+ elseif retryCount < 50 then
560+ -- Fail / Retry: The recipe isn't loaded yet.
561+ C_Timer .After (0.1 , function ()
562+ self :SelectRecipe (char , profID , recipeID , retryCount + 1 )
563+ end )
478564 end
479565end
480566
@@ -490,6 +576,19 @@ function CraftScanConfigPageMixin:OnLoad()
490576 self :SetTitle (L (' CraftScan' ))
491577
492578 self :SetUserPlaced (true )
579+
580+ CraftScan .Events :Register (' OPEN_RECIPE' , function (...)
581+ self :SelectRecipe (... )
582+ end )
583+
584+ -- Initialize the Maximize/Minimize button
585+ self .MaximizeMinimize :SetOnMaximizedCallback (function ()
586+ CraftScan .Events :Emit (' CONFIG_PAGE_MAXIMIZED' )
587+ self :SetMenuCollapsed (false )
588+ end )
589+ self .MaximizeMinimize :SetOnMinimizedCallback (function ()
590+ self :SetMenuCollapsed (true )
591+ end )
493592end
494593
495594CraftScanConfigMenuMixin = {}
@@ -588,7 +687,9 @@ function CraftScanConfigMenuMixin:OnLoad()
588687 end
589688 CraftScanConfigPage .Options :Hide ()
590689
591- self .activeOptions = configInfo .LoadOptions (configInfo )
690+ self .activeOptions =
691+ configInfo .LoadOptions (configInfo , CraftScanConfigPage .isMenuCollapsed )
692+ CraftScan .Events :Emit (' ACTIVE_OPTION_UPDATED' , self .activeOptions )
592693 self .activeOptions :Show ()
593694 -- CraftScanConfigPage.Options:SetScrollChild(self.activeOptions)
594695 CraftScanConfigPage .Options :Show ()
@@ -611,6 +712,7 @@ function CraftScanConfigMenuMixin:OnLoad()
611712 -- Pending as they are learned.
612713 self :RegisterEvent (' NEW_RECIPE_LEARNED' )
613714 self :RegisterEvent (' TRADE_SKILL_ITEM_CRAFTED_RESULT' )
715+ self :RegisterEvent (' TRADE_SKILL_DATA_SOURCE_CHANGED' )
614716 self :SetScript (' OnEvent' , function (self , event , ...)
615717 if event == ' NEW_RECIPE_LEARNED' then
616718 local recipeID , recipeLevel , baseRecipeID = ...
@@ -629,8 +731,10 @@ function CraftScanConfigMenuMixin:OnLoad()
629731 elseif event == ' TRADE_SKILL_ITEM_CRAFTED_RESULT' then
630732 local resultData = ...
631733 if resultData .concentrationSpent and resultData .concentrationSpent ~= 0 then
632- CraftScan .SaveConcentrationData ( )
734+ CraftScan .Events : Emit ( ' CONCENTRATION_UPDATED ' )
633735 end
736+ elseif event == ' TRADE_SKILL_DATA_SOURCE_CHANGED' then
737+ CraftScan .Events :Emit (' TRADESKILL_OPENED' )
634738 end
635739 end )
636740end
656760CraftScan .Config = {}
657761CraftScan .Config .OnConfigChange = OnConfigChange
658762
659- local menuInitialized = false
660763function CraftScanConfigMenuMixin :OnShow ()
661764 if menuInitialized then
662765 return
@@ -670,7 +773,7 @@ function CraftScanConfigMenuMixin:OnShow()
670773
671774 SetSortComparator (node , SortByHeaderLabel )
672775
673- node :Insert ({
776+ local generalNode = node :Insert ({
674777 order = 0 ,
675778 configInfo = {
676779 label = L (' General' ),
@@ -714,6 +817,8 @@ function CraftScanConfigMenuMixin:OnShow()
714817 end
715818
716819 self .ScrollBox :SetDataProvider (dataProvider , ScrollBoxConstants .RetainScrollPosition )
820+ self .selectionBehavior :SelectElementData (generalNode )
821+ self .ScrollBox :ScrollToElementData (generalNode )
717822end
718823
719824CraftScanConfigMenuHeaderMixin = {}
@@ -823,10 +928,11 @@ function CraftScan.Config.OnRecipeScanStateChange(configInfo, skipReload)
823928 newParent :Invalidate ()
824929
825930 -- Update the Options panel based on the new state.
826- configInfo .LoadOptions (configInfo )
931+ menu .activeOptions = configInfo .LoadOptions (configInfo , CraftScanConfigPage .isMenuCollapsed )
932+ CraftScan .Events :Emit (' ACTIVE_OPTION_UPDATED' , menu .activeOptions )
827933 end
828934
829- CraftScan .RecipeSchematicMenu . UpdateLabelText ( configInfo .recipeID )
935+ CraftScan .Events : Emit ( ' UPDATE_RECIPE_LABEL ' , configInfo .recipeID )
830936end
831937
832938function CraftScan .Config .UpdateProfession (char , profID , profConfig )
0 commit comments