@@ -41,6 +41,8 @@ function UI:Init()
4141
4242 --- @type nil | table<Enum.InventoryType , table<TUM_Tier , TUM_UI_ResultData[]>>
4343 self .results = nil ;
44+ --- @type nil | TUM_UI_ResultData[]
45+ self .todoListResults = nil ;
4446 self :BuildUI ();
4547 self :RegisterIntoBlizzMove ();
4648end
@@ -71,7 +73,7 @@ function UI:BuildUI()
7173 self :SetScript (' OnShow' , self .UpdateItems );
7274 self :SetScript (' OnUpdate' , self .OnUpdate );
7375
74- ButtonFrameTemplate_HidePortrait (self )
76+ ButtonFrameTemplate_HidePortrait (self );
7577 table.insert (UISpecialFrames , self :GetName ());
7678
7779 self :Hide ();
@@ -139,9 +141,9 @@ function UI:BuildUI()
139141 end
140142
141143 local classDropdown = CreateFrame (' DropdownButton' , nil , self , ' WowStyle1DropdownTemplate' );
142- self .classDropdown = classDropdown ;
144+ self .ClassDropdown = classDropdown ;
143145 do
144- classDropdown :SetPoint (' TOPRIGHT' , self , ' TOPRIGHT' , - 11 , - 32 );
146+ classDropdown :SetPoint (' TOPRIGHT' , self , ' TOPRIGHT' , - 18 , - 32 );
145147 classDropdown :SetWidth (150 );
146148 classDropdown :EnableMouseWheel (true );
147149 local numClasses = GetNumClasses ();
@@ -195,7 +197,7 @@ function UI:BuildUI()
195197 end
196198
197199 local seasonDropdown = CreateFrame (' DropdownButton' , nil , self , ' WowStyle1DropdownTemplate' );
198- self .seasonDropdown = seasonDropdown ;
200+ self .SeasonDropdown = seasonDropdown ;
199201 do
200202 seasonDropdown :SetPoint (' RIGHT' , classDropdown , ' LEFT' , - 10 , 0 );
201203 seasonDropdown :SetWidth (100 );
@@ -238,7 +240,7 @@ function UI:BuildUI()
238240 local updateButton = CreateFrame (' Button' , nil , self );
239241 self .UpdateButton = updateButton ;
240242 do
241- updateButton :SetPoint (' RIGHT' , self .seasonDropdown , ' LEFT' , - 6 , 0 );
243+ updateButton :SetPoint (' RIGHT' , self .SeasonDropdown , ' LEFT' , - 6 , 0 );
242244 updateButton :SetSize (32 , 32 );
243245 updateButton :SetHitRectInsets (4 , 4 , 4 , 4 );
244246 updateButton :SetNormalTexture (' Interface\\ Buttons\\ UI-SquareButton-Up' );
@@ -286,6 +288,7 @@ function UI:BuildUI()
286288 end
287289 end
288290
291+ -- grid table
289292 do
290293 local ROW_HEIGHT = 25 ;
291294 local COLUMN_WIDTH = 175 ;
@@ -480,8 +483,8 @@ function UI:BuildUI()
480483 end
481484
482485 if not isSyndicatorLoaded then
483- local syndicatorMessage = UI :CreateFontString (nil , ' OVERLAY' , ' GameFontNormal' );
484- self .syndicatorMessage = syndicatorMessage ;
486+ local syndicatorMessage = self :CreateFontString (nil , ' OVERLAY' , ' GameFontNormal' );
487+ self .SyndicatorMessage = syndicatorMessage ;
485488 do
486489 syndicatorMessage :SetPoint (' TOPLEFT' , self , ' TOPLEFT' , 12 , - 30 );
487490 syndicatorMessage :SetText (' Items from the bank or from alts can only be scanned if you have the addon "Syndicator" enabled.' );
@@ -532,6 +535,91 @@ function UI:BuildUI()
532535 end );
533536 currency :UpdateText ();
534537 end
538+
539+ local todoList = CreateFrame (' Frame' , nil , self , ' ButtonFrameTemplate' );
540+ self .TodoList = todoList ;
541+ do
542+ -- todoList setup
543+ do
544+ todoList :SetPoint (' TOPLEFT' , self , ' TOPRIGHT' , 0 , 0 );
545+ todoList :SetPoint (' BOTTOMLEFT' , self , ' BOTTOMRIGHT' , 0 , 0 );
546+ todoList :SetWidth (350 );
547+ todoList .Inset :SetPoint (" BOTTOMRIGHT" , - 4 , 4 );
548+ todoList :SetTitle (' Todo list' );
549+ todoList :EnableMouse (true );
550+ todoList :SetScript (" OnMouseDown" , function () self :Raise () end );
551+
552+ ButtonFrameTemplate_HidePortrait (todoList );
553+
554+ if TUM .db .UI_todoListShown == false then
555+ todoList :Hide ();
556+ end
557+ end
558+
559+ local todoListTitleBar = CreateFrame (' Frame' , nil , todoList , ' PanelDragBarTemplate' );
560+ todoList .TitleBar = todoListTitleBar ;
561+ do
562+ todoListTitleBar :SetTarget (self );
563+ todoListTitleBar :SetPoint (' TOPLEFT' , 0 , 0 );
564+ todoListTitleBar :SetPoint (' BOTTOMRIGHT' , todoList , ' TOPRIGHT' , 0 , - 32 );
565+ end
566+
567+ local scrollbar = CreateFrame (" EventFrame" , nil , todoList .Inset , " WowTrimScrollBar" );
568+ do
569+ scrollbar :SetPoint (" TOPRIGHT" );
570+ scrollbar :SetPoint (" BOTTOMRIGHT" );
571+ end
572+
573+ local scrollbox = CreateFrame (" Frame" , nil , todoList .Inset , " WowScrollBoxList" );
574+ do
575+ scrollbox :SetPoint (" TOPLEFT" , 6 , - 3 );
576+ scrollbox :SetPoint (" BOTTOMRIGHT" , scrollbar , " BOTTOMLEFT" , - 2 , 5 );
577+ end
578+
579+ local scrollView = CreateScrollBoxListLinearView ();
580+ do
581+ scrollView :SetElementExtent (20 ); -- Fixed height for each row; required as we're not using XML.
582+ scrollView :SetElementInitializer (" Button" , function (frame , entry )
583+ self :InitTodoListEntry (frame , entry );
584+ end );
585+ end
586+
587+ ScrollUtil .InitScrollBoxWithScrollBar (scrollbox , scrollbar , scrollView );
588+
589+ --- @param dataProvider DataProviderMixin
590+ function todoList :SetDataProvider (dataProvider )
591+ scrollbox :SetDataProvider (dataProvider );
592+ end
593+
594+ local toggleTodoListButton = CreateFrame (" Button" , nil , self , " WowStyle2IconButtonTemplate" );
595+ self .ToggleTodoListButton = toggleTodoListButton ;
596+ do
597+ toggleTodoListButton :SetSize (22 , 22 );
598+ toggleTodoListButton :SetFrameStrata (" HIGH" );
599+ toggleTodoListButton .normalAtlas = TUM .db .UI_todoListShown and " common-dropdown-icon-back" or " common-dropdown-icon-next" ;
600+ toggleTodoListButton :SetPoint (" RIGHT" , self , " TOPRIGHT" , 10 , - 48 );
601+ toggleTodoListButton :HookScript (" OnEnter" , function ()
602+ GameTooltip :SetOwner (toggleTodoListButton , " ANCHOR_RIGHT" );
603+ GameTooltip :SetText (" Toggle Todo List" );
604+ GameTooltip :Show ();
605+ end );
606+ toggleTodoListButton :HookScript (" OnLeave" , function () GameTooltip :Hide (); end );
607+ toggleTodoListButton :HookScript (" OnClick" , function () todoList :SetShown (not todoList :IsShown ()); end );
608+ toggleTodoListButton :OnButtonStateChanged ();
609+ end
610+
611+ todoList :HookScript (" OnShow" , function ()
612+ toggleTodoListButton .normalAtlas = " common-dropdown-icon-back" ;
613+ toggleTodoListButton :OnButtonStateChanged ();
614+ TUM .db .UI_todoListShown = true ;
615+ end );
616+ todoList :HookScript (" OnHide" , function ()
617+ toggleTodoListButton .normalAtlas = " common-dropdown-icon-next" ;
618+ toggleTodoListButton :OnButtonStateChanged ();
619+ TUM .db .UI_todoListShown = false ;
620+ end );
621+ end
622+
535623end
536624
537625function UI :ToggleUI ()
@@ -542,17 +630,24 @@ function UI:RegisterIntoBlizzMove()
542630 --- @type BlizzMoveAPI ?
543631 local BlizzMoveAPI = BlizzMoveAPI ; --- @diagnostic disable-line : undefined-global
544632 if BlizzMoveAPI then
633+ local frameName = self :GetName ();
545634 BlizzMoveAPI :RegisterAddOnFrames (
546635 {
547636 [addonName ] = {
548637 [self :GetName ()] = {
549638 SubFrames = {
550- [self :GetName () .. ' .TitleBar' ] = {},
639+ [frameName .. ' .TitleBar' ] = {},
640+ [frameName .. ' .TodoList' ] = {
641+ Detachable = true ,
642+ SubFrames = {
643+ [frameName .. ' .TodoList.TitleBar' ] = {},
644+ },
645+ },
551646 },
552647 },
553648 },
554649 }
555- )
650+ );
556651 end
557652end
558653
@@ -648,7 +743,52 @@ function UI:OnUpdate()
648743 end
649744 end
650745 end
746+
747+ local dataProvider = CreateDataProvider (self .todoListResults )
748+ self .TodoList :SetDataProvider (dataProvider );
749+ end
750+ end
751+
752+ --- @param frame TUM_UI_TodoList_ElementFrame
753+ --- @param entry TUM_UI_ResultData
754+ function UI :InitTodoListEntry (frame , entry )
755+ --- @class TUM_UI_TodoList_ElementFrame
756+ local frame = frame ;
757+
758+ if not frame .Text then
759+ frame .Text = frame :CreateFontString (nil , " OVERLAY" , " GameFontHighlight" );
760+ frame .Text :SetJustifyH (" LEFT" );
761+ frame .Text :SetAllPoints (frame );
762+ end
763+
764+ if not frame .HighlightBackground then
765+ frame .HighlightBackground = frame :CreateTexture (nil , " BACKGROUND" );
766+ frame .HighlightBackground :SetAllPoints (frame );
767+ frame .HighlightBackground :Hide ();
768+ frame .HighlightBackground :SetColorTexture (1 , 1 , 1 , 0.1 );
769+ end
770+
771+ local text = UPGRADE_MARKUP .. ' ' .. entry .itemLink ;
772+ if entry .distance > 0 then
773+ text = WARBAND_MARKUP .. ' ' .. text ;
651774 end
775+ if entry .upgradeLevel > 0 then
776+ text = text .. (' %d/%d' ):format (entry .upgradeLevel , entry .maxUpgradeLevel );
777+ end
778+
779+ frame .Text :SetText (text );
780+ frame :SetScript (" OnEnter" , function ()
781+ GameTooltip :SetOwner (frame , " ANCHOR_RIGHT" , - 80 , 0 );
782+ GameTooltip :AddDoubleLine (" Location" , entry .location , 1 , 1 , 1 , 1 , 1 , 1 );
783+ GameTooltip :AppendInfoWithSpacer (" GetHyperlink" , entry .itemLink );
784+ GameTooltip :Show ();
785+ frame .HighlightBackground :Show ();
786+ end );
787+
788+ frame :SetScript (" OnLeave" , function ()
789+ GameTooltip :Hide ();
790+ frame .HighlightBackground :Hide ();
791+ end );
652792end
653793
654794local ARMOR_SEARCH_TERMS = {
703843--- @param scanResult SyndicatorSearchResult
704844--- @param classID number
705845--- @param seasonID number
706- --- @return nil | TUM_UI_ResultData info
707- --- @return nil | TUM_UI_ResultData upgradedInfo
846+ --- @return nil | TUM_UI_ResultData catalystInfo
847+ --- @return nil | TUM_UI_ResultData upgradedCatalystInfo
848+ --- @return nil | TUM_UI_ResultData upgradeInfo
708849local function checkResult (scanResult , classID , seasonID )
709850 if
710851 scanResult .source .guild -- ignore guild banks, might add some filter setting later
@@ -781,7 +922,8 @@ local function checkResult(scanResult, classID, seasonID)
781922 };
782923 end
783924
784- if tumResult .catalystUpgradeAppearanceMissing or (isItemCatalysed and tumResult .upgradeAppearanceMissing ) then
925+ local upgradeIsCatalyst = tumResult .catalystUpgradeAppearanceMissing or (isItemCatalysed and tumResult .upgradeAppearanceMissing );
926+ if tumResult .catalystUpgradeAppearanceMissing or tumResult .upgradeAppearanceMissing then
785927 --- @type TUM_UI_ResultData
786928 upgradedInfo = {
787929 slot = itemSlot ,
@@ -797,7 +939,7 @@ local function checkResult(scanResult, classID, seasonID)
797939 };
798940 end
799941
800- return info , upgradedInfo ;
942+ return info , upgradeIsCatalyst and upgradedInfo , tumResult . upgradeAppearanceMissing and upgradedInfo ;
801943end
802944
803945--- @param result SyndicatorSearchResult
@@ -807,15 +949,18 @@ local function handleResult(result)
807949 end
808950 local item = Item :CreateFromItemLink (result .itemLink );
809951 item :ContinueOnItemLoad (function ()
810- local info , upgradeInfo = checkResult (result , UI .selectedClass , UI .selectedSeason );
811- if info or upgradeInfo then
952+ local catalystInfo , upgradedCatalystInfo , upgradeInfo = checkResult (result , UI .selectedClass , UI .selectedSeason );
953+ if catalystInfo or upgradeInfo then
812954 UI .deferNewResult = true ;
813955 end
814- if info then
815- tinsert (UI .results [info .slot ][info .tier ], info );
956+ if catalystInfo then
957+ tinsert (UI .results [catalystInfo .slot ][catalystInfo .tier ], catalystInfo );
958+ end
959+ if upgradedCatalystInfo then
960+ tinsert (UI .results [upgradedCatalystInfo .slot ][upgradedCatalystInfo .tier ], upgradedCatalystInfo );
816961 end
817962 if upgradeInfo then
818- tinsert (UI .results [ upgradeInfo . slot ][ upgradeInfo . tier ] , upgradeInfo );
963+ tinsert (UI .todoListResults , upgradeInfo );
819964 end
820965 end );
821966end
@@ -827,6 +972,7 @@ function UI:UpdateItems()
827972 end
828973 self .pending = self .selectedClass .. ' |' .. self .selectedSeason ;
829974 self .results = initResults ();
975+ self .todoListResults = {};
830976 self .deferNewResult = true ;
831977 if isSyndicatorLoaded then
832978 local term = buildSyndicatorSearchTerm (self .selectedClass );
0 commit comments