11from  __future__ import  annotations 
22import  time 
33import  sys 
4- from  typing  import  Any 
4+ from  typing  import  Any ,  Optional 
55import  typing 
66from  worlds  import  AutoWorldRegister , network_data_package 
77import  json 
@@ -192,11 +192,11 @@ def on_package(self, cmd: str, args: dict):
192192                logger .info (f"Slot data: { args ['slot_data' ]}  )
193193
194194            self .ui .build_tracker_and_locations_table ()
195-             self .ui .update_tracker_and_locations_table (update_highlights = True )
195+             self .ui .request_update_tracker_and_locations_table (update_highlights = True )
196196        elif  cmd  in  {"ReceivedItems" }:
197-             self .ui .update_tracker_and_locations_table (update_highlights = True )
197+             self .ui .request_update_tracker_and_locations_table (update_highlights = True )
198198        elif  cmd  in  {"RoomUpdate" }:
199-             self .ui .update_tracker_and_locations_table (update_highlights = False )
199+             self .ui .request_update_tracker_and_locations_table (update_highlights = False )
200200
201201    def  on_deathlink (self , data : typing .Dict [str , typing .Any ]) ->  None :
202202        super ().on_deathlink (data )
@@ -206,12 +206,12 @@ def on_deathlink(self, data: typing.Dict[str, typing.Any]) -> None:
206206
207207    def  on_tracker_updated (self , reachable_locations : list [str ]):
208208        self .tracker_reachable_locations  =  reachable_locations 
209-         self .ui .update_tracker_and_locations_table (update_highlights = True )
209+         self .ui .request_update_tracker_and_locations_table (update_highlights = True )
210210
211211    def  on_tracker_events (self , events : list [str ]):
212212        self .tracker_reachable_events  =  events 
213213        if  events :
214-             self .ui .update_tracker_and_locations_table (update_highlights = True )
214+             self .ui .request_update_tracker_and_locations_table (update_highlights = True )
215215
216216    def  run_gui (self ):
217217        """Import kivy UI system from make_gui() and start running it as self.ui_task.""" 
@@ -282,6 +282,9 @@ class ManualManager(ui):
282282            active_item_accordion  =  0 
283283            active_location_accordion  =  0 
284284
285+             update_requested_time : Optional [float ] =  None 
286+             update_requested_highlights : bool  =  False 
287+ 
285288            ctx : ManualContext 
286289
287290            def  __init__ (self , ctx ):
@@ -369,7 +372,7 @@ def update_hints(self):
369372
370373                if  rebuild :
371374                    self .build_tracker_and_locations_table ()
372-                 self .update_tracker_and_locations_table ()
375+                 self .request_update_tracker_and_locations_table ()
373376
374377            def  build_tracker_and_locations_table (self ):
375378                self .tracker_and_locations_panel .clear_widgets ()
@@ -438,6 +441,9 @@ def build_tracker_and_locations_table(self):
438441                if  not  victory_categories :
439442                    victory_categories .add ("(No Category)" )
440443
444+                 for  category  in  self .listed_locations :
445+                     self .listed_locations [category ].sort (key = self .ctx .location_names .lookup_in_game )
446+ 
441447                items_length  =  len (self .ctx .items_received )
442448                tracker_panel_scrollable  =  TrackerLayoutScrollable (do_scroll = (False , True ), bar_width = 10 )
443449                tracker_panel  =  TreeView (root_options = dict (text = "Items Received (%d)"  %  (items_length )), size_hint_y = None )
@@ -501,6 +507,19 @@ def build_tracker_and_locations_table(self):
501507                self .tracker_and_locations_panel .add_widget (tracker_panel_scrollable )
502508                self .tracker_and_locations_panel .add_widget (locations_panel_scrollable )
503509
510+             def  check_for_requested_update (self ):
511+                 current_time  =  time .time ()
512+ 
513+                 # wait 0.25 seconds before executing update, in case there are multiple update requests coming in 
514+                 if  self .update_requested_time  and  current_time  -  self .update_requested_time  >=  0.25 :
515+                     self .update_requested_time  =  None 
516+                     self .update_tracker_and_locations_table (self .update_requested_highlights )
517+                     self .update_requested_highlights  =  False 
518+ 
519+             def  request_update_tracker_and_locations_table (self , update_highlights = False ):
520+                 self .update_requested_time  =  time .time ()
521+                 self .update_requested_highlights  =  update_highlights  or  self .update_requested_highlights  # if any of the requests wanted highlights, do highlight 
522+ 
504523            def  update_tracker_and_locations_table (self , update_highlights = False ):
505524                items_length  =  len (self .ctx .items_received )
506525                locations_length  =  len (self .ctx .missing_locations )
@@ -532,7 +551,10 @@ def update_tracker_and_locations_table(self, update_highlights=False):
532551                                category_count  =  0 
533552                                category_unique_name_count  =  0 
534553
535-                                 # Label (for existing item listings) 
554+                                 existing_item_labels  =  []
555+                                 bold_item_labels  =  []
556+ 
557+                                 # for items that were already listed, determine if the qty changed. if it did, add them to the list to be bolded 
536558                                for  item  in  category_grid .children :
537559                                     if  type (item ) is  Label :
538560                                        # Get the item name from the item Label, minus quantity, then do a lookup for count 
@@ -544,28 +566,37 @@ def update_tracker_and_locations_table(self, update_highlights=False):
544566                                        # Update the label quantity 
545567                                        item .text = "%s (%s)"  %  (item_name , item_count )
546568
547-                                         if  update_highlights :
548-                                             item .bold  =  True  if  old_item_text  !=  item .text  else  False 
569+                                         if  update_highlights  and  (old_item_text  !=  item .text ):
570+                                             bold_item_labels .append (item_name )
571+ 
572+                                         existing_item_labels .append (item_name )
573+ 
574+                                 # instead of reusing existing item listings, clear it all out and re-draw with the sorted list 
575+                                 category_grid .clear_widgets ()
576+                                 self .listed_items [category_name ].clear ()
549577
550-                                         if  item_count  >  0 :
551-                                             category_count  +=  item_count 
552-                                             category_unique_name_count  +=  1 
578+                                 # Label (for all item listings) 
579+                                 sorted_items_received  =  sorted ([
580+                                     i .item  for  i  in  self .ctx .items_received  
581+                                 ], key = self .ctx .item_names .lookup_in_game )
553582
554-                                 # Label (for new item listings) 
555-                                 for  network_item  in  self .ctx .items_received :
556-                                     item_name  =  self .ctx .item_names .lookup_in_game (network_item .item )
583+                                 for  network_item  in  sorted_items_received :
584+                                     item_name  =  self .ctx .item_names .lookup_in_game (network_item )
557585                                    item_data  =  self .ctx .get_item_by_name (item_name )
558586
559587                                    if  "category"  not  in item_data  or  not  item_data ["category" ]:
560588                                        item_data ["category" ] =  ["(No Category)" ]
561589
562-                                     if  category_name  in  item_data ["category" ] and  network_item . item  not  in self .listed_items [category_name ]:
563-                                         item_count  =  len (list (i  for  i  in  self .ctx .items_received  if  i .item  ==  network_item . item ))
590+                                     if  category_name  in  item_data ["category" ] and  network_item  not  in self .listed_items [category_name ]:
591+                                         item_count  =  len (list (i  for  i  in  self .ctx .items_received  if  i .item  ==  network_item ))
564592                                        item_text  =  Label (text = "%s (%s)"  %  (item_name , item_count ),
565593                                                    size_hint = (None , None ), height = 30 , width = 400 , bold = True )
566594
595+                                         # if the item was previously listed and was bold, or if it wasn't previously listed at all, make it bold 
596+                                         item_text .bold  =  (update_highlights  and  (item_name  in  bold_item_labels  or  item_name  not  in existing_item_labels ))
597+ 
567598                                        category_grid .add_widget (item_text )
568-                                         self .listed_items [category_name ].append (network_item . item )
599+                                         self .listed_items [category_name ].append (network_item )
569600
570601                                        category_count  +=  item_count 
571602                                        category_unique_name_count  +=  1 
@@ -687,6 +718,9 @@ def victory_button_callback(self, button):
687718
688719async  def  game_watcher_manual (ctx : ManualContext ):
689720    while  not  ctx .exit_event .is_set ():
721+         if  ctx .ui :
722+             ctx .ui .check_for_requested_update ()
723+ 
690724        if  ctx .syncing  ==  True :
691725            sync_msg  =  [{'cmd' : 'Sync' }]
692726            if  ctx .locations_checked :
0 commit comments