All Downloads are FREE. Search and download functionalities are using the official Maven repository.

us.ihmc.simulationconstructionset.gui.hierarchyTree.NamespaceHierarchyTree Maven / Gradle / Ivy

There is a newer version: 0.25.2
Show newest version
package us.ihmc.simulationconstructionset.gui.hierarchyTree;

import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.filechooser.FileFilter;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import us.ihmc.simulationconstructionset.commands.WriteDataCommandExecutor;
import us.ihmc.simulationconstructionset.gui.CreatedNewRegistriesListener;
import us.ihmc.simulationconstructionset.gui.EventDispatchThreadHelper;
import us.ihmc.simulationconstructionset.gui.ForcedRepaintPopupMenu;
import us.ihmc.simulationconstructionset.gui.RegistrySettingsChangedListener;
import us.ihmc.simulationconstructionset.util.RegularExpression;
import us.ihmc.simulationconstructionset.util.SimpleFileWriter;
import us.ihmc.yoVariables.registry.YoRegistry;
import us.ihmc.yoVariables.variable.YoVariable;

public class NamespaceHierarchyTree extends JScrollPane implements MouseListener, FocusListener, CreatedNewRegistriesListener
{
   private static final long serialVersionUID = -8489413083414697473L;
   private JTree tree;
   private JFileChooser fileChooser = new JFileChooser();
   private DefaultTreeModel model;
   private DefaultMutableTreeNode top;
   private LinkedHashMap registryTreeNodeMap = new LinkedHashMap<>();
   private LinkedHashMap treeNodeRegistryMap = new LinkedHashMap<>();
   private final JFrame frame;
   private final WriteDataCommandExecutor writeDataCommandExecutor;

   private final RegistrySelectedListener registrySelectedListener;

   protected JPopupMenu popupMenu;

   private final YoRegistry root;
   private List registrySettingsChangedListeners = new ArrayList<>();

   private String filterText = "";
   private boolean showOnlyParameters = false;

   public NamespaceHierarchyTree(RegistrySelectedListener namespaceSelectedListener, JFrame frame, WriteDataCommandExecutor writeDataCommandExecutor,
                                 YoRegistry rootRegistry)
   {
      super();

      EventDispatchThreadHelper.checkThatInEventDispatchThread();

      registrySelectedListener = namespaceSelectedListener;
      root = rootRegistry;
      topOfTreeRegistry = root;
      this.frame = frame;
      this.writeDataCommandExecutor = writeDataCommandExecutor;

      top = new DefaultMutableTreeNode(rootRegistry.getNamespace().getName());
      model = new DefaultTreeModel(top);
      tree = new JTree();
      tree.setModel(model);
      tree.setShowsRootHandles(true);
      this.add(tree);
      setViewportView(tree);
      tree.setRootVisible(false);
      tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
      tree.addMouseListener(this);
      tree.setToggleClickCount(0);

      initPopupMenu();
      setUpTree(rootRegistry);

      tree.setCellRenderer(new NamespaceHierarchyNodeRenderer(treeNodeRegistryMap));
   }

   public void filter(String filterText)
   {
      this.filterText = filterText;
      createdNewRegistries();
   }

   public void filterParameters(boolean showOnlyParameters)
   {
      this.showOnlyParameters = showOnlyParameters;
      createdNewRegistries();
   }

   private boolean needToSetupTree = true;
   private YoRegistry topOfTreeRegistry;

   @Override
   public void paintComponent(Graphics g)
   {
      if (needToSetupTree)
      {
         setUpTree(topOfTreeRegistry);
         needToSetupTree = false;
      }

      super.paintComponent(g);
   }

   private void setUpTree(final YoRegistry currentregistry)
   {
      //TODO: This is incorrect but exo breaks when using invokelater for some reason.
      // Also, reads registry childeren without locks.
      //      EventDispatchThreadHelper.justRun(new Runnable(){
      //
      //         public void run()
      //         {
      EventDispatchThreadHelper.checkThatInEventDispatchThread();

      addNode(currentregistry);

      for (YoRegistry child : currentregistry.getChildren())
      {
         setUpTree(child);
      }
      //         }});
   }

   private void initPopupMenu()
   {
      popupMenu = new ForcedRepaintPopupMenu();
      JMenuItem toggleVaribleSend = new JMenuItem("Toggle Variable Send");
      toggleVaribleSend.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            toggleVariableSend(e);
            popupMenu.setVisible(false);
         }
      });
      popupMenu.add(toggleVaribleSend);

      JMenuItem recursiveToggleVaribleSend = new JMenuItem("Recursive Toggle Variable Send");
      recursiveToggleVaribleSend.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            recursiveToggleVariableSend(e);
            popupMenu.setVisible(false);
         }
      });
      popupMenu.add(recursiveToggleVaribleSend);

      JMenuItem toggleVariableLog = new JMenuItem("Toggle Variable Log");
      toggleVariableLog.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            toggleVariableLog(e);
            popupMenu.setVisible(false);
         }
      });
      popupMenu.add(toggleVariableLog);

      JMenuItem recursiveToggleVariableLog = new JMenuItem("Recursive Toggle Variable Log");
      recursiveToggleVariableLog.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            recursiveToggleVariableLog(e);
            popupMenu.setVisible(false);
         }
      });
      popupMenu.add(recursiveToggleVariableLog);

      JMenuItem exportBinaryRegistryData = new JMenuItem("Export to binary format");
      exportBinaryRegistryData.addActionListener(new ActionListener()
      {

         @Override
         public void actionPerformed(ActionEvent e)
         {
            exportRegistryData(e, true);
            popupMenu.setVisible(false);
         }
      });
      popupMenu.add(exportBinaryRegistryData);

      JMenuItem exportASCIIRegistryData = new JMenuItem("Export to ASCII format");
      exportASCIIRegistryData.addActionListener(new ActionListener()
      {

         @Override
         public void actionPerformed(ActionEvent e)
         {
            exportRegistryData(e, false);
            popupMenu.setVisible(false);
         }
      });
      popupMenu.add(exportASCIIRegistryData);

      JMenuItem save = new JMenuItem("Save Configuration");
      save.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            saveConfiguration();
            popupMenu.setVisible(false);
         }
      });
      popupMenu.add(save);

      JMenuItem load = new JMenuItem("Load Configuration");
      load.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            loadConfiguration();
            popupMenu.setVisible(false);
         }
      });
      popupMenu.add(load);

      popupMenu.addFocusListener(this);

      // tree.addFocusListener(this);
      // this.addFocusListener(this);
   }

   private void addNode(YoRegistry registry)
   {
      EventDispatchThreadHelper.checkThatInEventDispatchThread();

      if (!tree.isExpanded(new TreePath(top.getPath())))
      {
         tree.expandPath(new TreePath(top.getPath()));
      }

      boolean match = RegularExpression.check(registry.getNamespace().getName(), filterText);
      if (showOnlyParameters && match)
      {
         match = registry.hasParametersDeep();
      }

      if (match)
      {
         // create the top of the tree
         if (registry.getParent() == null || !registryTreeNodeMap.containsKey(registry.getParent()))
         {
            DefaultMutableTreeNode newTopLevelAncestor = new DefaultMutableTreeNode(registry.getNamespace().getShortName());
            registryTreeNodeMap.put(registry, newTopLevelAncestor);
            treeNodeRegistryMap.put(newTopLevelAncestor, registry);
            top.add(newTopLevelAncestor);

            model.setRoot(top);
         }
         else
         {
            DefaultMutableTreeNode newChild = new DefaultMutableTreeNode(registry.getNamespace().getShortName());
            registryTreeNodeMap.put(registry, newChild);
            treeNodeRegistryMap.put(newChild, registry);
            registryTreeNodeMap.get(registry.getParent()).add(newChild);
         }
      }
   }

   public void showNamespace(YoRegistry registry)
   {
      if (registryTreeNodeMap.containsKey(registry))
      {
         TreePath pathToNamespace = new TreePath(registryTreeNodeMap.get(registry).getPath());

         tree.expandPath(pathToNamespace);
         tree.scrollPathToVisible(pathToNamespace);
         tree.setSelectionPath(pathToNamespace);
      }
      else
      {
         System.err.println("Warning: " + registry.getNamespace().getName() + " not found.");
      }
   }

   @Override
   public void mouseClicked(MouseEvent arg0)
   {
      if (arg0.getClickCount() == 2)
      {
         TreePath treePath = tree.getPathForLocation(arg0.getX(), arg0.getY());
         if ((treePath != null) && (treePath.getPathCount() >= 1))
         {
            if (registryTreeNodeMap.containsValue(treePath.getLastPathComponent()))
            {
               YoRegistry registry = treeNodeRegistryMap.get(treePath.getLastPathComponent());
               registrySelectedListener.registryWasSelected(registry);
            }
         }
      }

   }

   @Override
   public void mouseEntered(MouseEvent arg0)
   {
   }

   @Override
   public void mouseExited(MouseEvent arg0)
   {
   }

   @Override
   public void mousePressed(MouseEvent arg0)
   {
      if (arg0.isPopupTrigger())
      {
         popupMenu.show((Component) arg0.getSource(), arg0.getX(), arg0.getY());
      }
   }

   @Override
   public void mouseReleased(MouseEvent arg0)
   {
      if (arg0.isPopupTrigger())
      {
         popupMenu.show((Component) arg0.getSource(), arg0.getX(), arg0.getY());
      }
   }

   private void recursiveToggleVariableSend(ActionEvent arg0)
   {
      boolean toggleSend = true;
      boolean toggleLog = false;
      boolean recursive = true;

      toggleVariableSendOrLog(arg0, toggleSend, toggleLog, recursive);
   }

   private void toggleVariableSend(ActionEvent arg0)
   {
      boolean toggleSend = true;
      boolean toggleLog = false;
      boolean recursive = false;

      toggleVariableSendOrLog(arg0, toggleSend, toggleLog, recursive);
   }

   private void recursiveToggleVariableLog(ActionEvent arg0)
   {
      boolean toggleSend = false;
      boolean toggleLog = true;
      boolean recursive = true;

      toggleVariableSendOrLog(arg0, toggleSend, toggleLog, recursive);
   }

   private void toggleVariableLog(ActionEvent arg0)
   {
      boolean toggleSend = false;
      boolean toggleLog = true;
      boolean recursive = false;

      toggleVariableSendOrLog(arg0, toggleSend, toggleLog, recursive);
   }

   private void toggleVariableSendOrLog(ActionEvent arg0, boolean toggleSend, boolean toggleLog, boolean recursive)
   {
      TreePath[] selectionPaths = tree.getSelectionPaths();
      List changedRegistries = new ArrayList<>();
      for (int i = 0; i < selectionPaths.length; i++)
      {
         TreePath path = selectionPaths[i];
         TreeNode parentNode = (TreeNode) path.getLastPathComponent();

         YoRegistry parentRegistry = treeNodeRegistryMap.get(parentNode);

         recursiveToggleVariableSendOrLog(recursive, toggleSend, toggleLog, parentNode, parentRegistry, changedRegistries);
      }

      notifyRegistrySettingsChangedListeners(changedRegistries);
   }

   private void exportRegistryData(ActionEvent e, final boolean binary)
   {
      TreePath[] selectionPaths = tree.getSelectionPaths();
      List allVariables = new ArrayList<>();

      for (int i = 0; i < selectionPaths.length; i++)
      {
         TreePath path = selectionPaths[i];
         TreeNode parentNode = (TreeNode) path.getLastPathComponent();

         YoRegistry parentRegistry = treeNodeRegistryMap.get(parentNode);
         allVariables.addAll(parentRegistry.collectSubtreeVariables());
      }

      FileFilter filterFilter = new FileFilter()
      {

         @Override
         public String getDescription()
         {
            if (binary)
               return ".data.gz";
            else
               return ".m";
         }

         @Override
         public boolean accept(File f)
         {
            if (f.isDirectory())
               return true;

            if (f.getName().toLowerCase().endsWith(getDescription()))
               return true;

            else
               return false;
         }
      };

      fileChooser.setFileFilter(filterFilter);

      if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION)
      {
         String fileExt = filterFilter.getDescription();
         File chosenFile = fileChooser.getSelectedFile();
         String fileName = chosenFile.getName();

         if (!fileName.endsWith(fileExt))
         {
            fileName = fileName.concat(fileExt);

            if (!chosenFile.getName().equals(fileName))
            {
               chosenFile = new File(chosenFile.getParent(), fileName);
            }
         }

         writeDataCommandExecutor.writeData(allVariables, binary, binary ? true : false, chosenFile);
      }

   }

   private void recursiveToggleVariableSendOrLog(boolean recursive, boolean toggleSend, boolean toggleLog, TreeNode parentNode, YoRegistry parentRegistry,
                                                 List changedRegistries)
   {
      changedRegistries.add(parentRegistry);
      model.nodeChanged(parentNode);

      if (recursive)
      {
         Enumeration childrenNodes = parentNode.children();

         while (childrenNodes.hasMoreElements())
         {
            TreeNode childNode = childrenNodes.nextElement();
            YoRegistry childRegistry = treeNodeRegistryMap.get(childNode);

            recursiveToggleVariableSendOrLog(recursive, toggleSend, toggleLog, childNode, childRegistry, changedRegistries);
         }
      }
   }

   @Override
   public void focusGained(FocusEvent e)
   {
   }

   @Override
   public void focusLost(FocusEvent e)
   {
      //    popupMenu.setVisible(false);
   }

   public void loadConfiguration()
   {
      File configs = new File("Configurations");
      JFileChooser openDialog = new JFileChooser(configs);
      File selectedFile = null;
      if (JFileChooser.APPROVE_OPTION == openDialog.showOpenDialog(openDialog))
      {
         selectedFile = openDialog.getSelectedFile();
      }

      loadConfiguration(selectedFile);
   }

   public void loadConfiguration(File selectedFile)
   {
      if (selectedFile != null)
      {
         if (selectedFile.exists())
         {
            List treeNodes = root.collectSubtreeRegistries();

            // getAllRegistrys(rootRegistry, treeNodes);

            // System.out.println(i+" "+realCound+" "+rootRegistry.createVarListsIncludingChildren().size());

            notifyRegistrySettingsChangedListeners();
         }
      }
   }

   private void notifyRegistrySettingsChangedListeners()
   {
      for (RegistrySettingsChangedListener listener : registrySettingsChangedListeners)
      {
         listener.registrySettingsChanged();
      }
   }

   private void notifyRegistrySettingsChangedListeners(List yoVariableRegistries)
   {
      for (RegistrySettingsChangedListener listener : registrySettingsChangedListeners)
      {
         listener.registrySettingsChanged(yoVariableRegistries);
      }
   }

   public void saveConfiguration()
   {
      System.out.println("save");
      File configs = new File("Configurations");
      JFileChooser saveDialog = new JFileChooser(configs);
      File selectedFile = null;
      if (JFileChooser.APPROVE_OPTION == saveDialog.showSaveDialog(this))
      {
         selectedFile = saveDialog.getSelectedFile();
      }

      if (selectedFile != null)
      {
         SimpleFileWriter writer = new SimpleFileWriter(selectedFile);
         List treeNodes = root.collectSubtreeRegistries();

         String outString = "";
         for (YoRegistry node : treeNodes)
         {
            outString += node.getNamespace().getName() + "\n";
         }

         writer.write(outString);
         writer.close();
      }
   }

   @Override
   public void createdNewRegistries()
   {
      top.removeAllChildren();
      registryTreeNodeMap.clear();
      treeNodeRegistryMap.clear();

      topOfTreeRegistry = root;
      needToSetupTree = true;
      //      setUpTree(root);
   }

   public void addRegistrySettingsChangedListener(RegistrySettingsChangedListener listener)
   {
      registrySettingsChangedListeners.add(listener);
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy