text: #
  from __future__ import annotations
  from typing import TYPE_CHECKING
  
  import tkinter
  
  import pyted.monet_widget_types as pyted_widget_types
  if TYPE_CHECKING:
      from pyted.pyted_code.pyted_core import PytedCore
  
  
  class NavigatorTree:
      """Widget attribute frame
  
      Frame that shows the widget attributes (including variables), and events. The frame additionally shows the row
      and column attributes of the parent.
      """
  
      def __init__(self, pyted_core: PytedCore):
          self.pyted_core = pyted_core
          self.widgets = pyted_core.widgets
  
          self.navigator_tree = pyted_core.pyted_window.navigator_tree
          self.navigator_tree.tag_bind('project', '<ButtonRelease-1>',
                                       self.navigator_tree_clicked)
          self.navigator_tree.tag_bind('toplevel', '<ButtonRelease-1>',
                                       self.navigator_tree_clicked)
          self.navigator_tree.tag_bind('var', '<ButtonRelease-1>',
                                       self.navigator_tree_clicked)
          self.navigator_tree.tag_bind('widget', '<ButtonRelease-1>',
                                       self.navigator_tree_clicked)
  
      # called when widget in navigation tree clicked
      def navigator_tree_clicked(self, _event):
          widget_toolbox = self.pyted_core.widget_toolbox
          widget_toolbox.widget_in_toolbox_chosen = None
          widget_toolbox.pointer_button.invoke()
  
          pyte_widget = None
          for pyte_widget in self.widgets.widget_list:
              if pyte_widget.name == self.navigator_tree.focus():
                  break
          self.pyted_core.select_widget(pyte_widget)
  
      def build_navigator_tree(self) -> None:
          """
          Update navigator tree to show all widgets
  
          Clears the navigator tree and updates it with all widgets in the project as held in the list self.widgets.
  
          Note that the first widget in the list must be the TopLevel widget, but all the other widgets may be in any
          order.
          """
          # remove old items from navigator tree
          for i in self.navigator_tree.get_children():
              self.navigator_tree.delete(i)
  
          # put project widget as main branch
          widget = self.widgets.widget_list[0]
          self.navigator_tree.insert('', 'end', widget.name,
                                     text=widget.name, values='"' + type(widget).__name__ + '"',
                                     tags='project')
          self.navigator_tree.item(widget.name, open=True)
          project_name = widget.name
  
          # put vars into tree
          for widget in self.widgets.widget_list:
              try:
                  is_var = widget.is_var
              except AttributeError:
                  is_var = False
              if is_var:
                  self.navigator_tree.insert(project_name, 'end', widget.name,
                                             text=widget.name, values='"' + type(widget).__name__ + '"',
                                             tags='var')
  
          # put widgets into tree
          widget = self.widgets.find_top_widget()
          self.navigator_tree.insert(self.widgets.widget_list[0].name, 'end', widget.name,
                                     text=widget.name, values='"' + type(widget).__name__ + '"',
                                     tags='toplevel')
          self.navigator_tree.item(widget.name, open=True)
          self.build_navigator_tree_parent(widget)
          if self.pyted_core.selected_widget is not None:
              self.navigator_tree.focus(self.pyted_core.selected_widget.name)
              self.navigator_tree.selection_set(self.pyted_core.selected_widget.name)
  
      def build_navigator_tree_parent(self, parent: pyted_widget_types) -> None:
          """
          Adds items to the navigator tree with the parent specified
  
          Adds all widgets with the parent specified as items to the navigator tree. Container widgets are also added
          with the branch opened and the function called recursively to fill the tree.
  
          :param parent: parent of widgets to be added to navigator tree
          """
          for widget in self.widgets.widget_list:
              try:
                  widget_type = widget.type
              except AttributeError:
                  widget_type = None
              if not widget_type == tkinter.Toplevel:
                  if widget.parent == parent.name:
                      self.navigator_tree.insert(widget.parent, 'end', widget.name,
                                                 text=widget.name, values='"' + type(widget).__name__ + '"',
                                                 tags='widget')
                      # TODO: change the below to use container widget superclass
                      if (isinstance(widget, pyted_widget_types.Frame) or isinstance(widget, pyted_widget_types.Notebook)
                              or isinstance(widget, pyted_widget_types.PanedWindow)):
                          self.navigator_tree.item(widget.name, open=True)
                          self.build_navigator_tree_parent(widget)
  
      def navigator_tree_select_item(self):
          if self.pyted_core.selected_widget is not None:
              self.navigator_tree.focus(self.pyted_core.selected_widget.name)
              self.navigator_tree.selection_set(self.pyted_core.selected_widget.name)
              self.navigator_tree.see(self.pyted_core.selected_widget.name)
  
      def navigator_tree_change_item_name(self, pyte_widget, old_name):
          item_index = self.navigator_tree.index(old_name)
          item_parent = self.navigator_tree.parent(old_name)
          old_item_is_open = self.navigator_tree.item(old_name, 'open')
          # print(old_item_is_open)
          self.navigator_tree.insert(item_parent, item_index, pyte_widget.name,
                                     text=pyte_widget.name, values='"' + type(pyte_widget).__name__ + '"',
                                     tags='widget')
          children = self.navigator_tree.get_children(old_name)
          for child in children:
              self.navigator_tree.move(child, pyte_widget.name, tkinter.END)
          self.navigator_tree.item(pyte_widget.name, open=old_item_is_open)
          self.navigator_tree.delete(old_name)
          if self.pyted_core.selected_widget is not None:
              self.navigator_tree.focus(self.pyted_core.selected_widget.name)
              self.navigator_tree.selection_set(self.pyted_core.selected_widget.name)
  