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

us.ihmc.simulationconstructionset.gui.yoVariableSearch.YoVariableSearchPanel Maven / Gradle / Ivy

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

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.function.Predicate;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import us.ihmc.euclid.referenceFrame.ReferenceFrame;
import us.ihmc.graphicsDescription.graphInterfaces.SelectedVariableHolder;
import us.ihmc.simulationconstructionset.gui.BookmarkedVariablesHolder;
import us.ihmc.simulationconstructionset.gui.BookmarkedVariablesPanel;
import us.ihmc.simulationconstructionset.gui.DoubleClickListener;
import us.ihmc.simulationconstructionset.gui.EntryBoxArrayTabbedPanel;
import us.ihmc.simulationconstructionset.gui.GraphArrayPanel;
import us.ihmc.simulationconstructionset.gui.YoEntryBox;
import us.ihmc.simulationconstructionset.gui.YoVariableExplorerTabbedPane;
import us.ihmc.simulationconstructionset.util.AdditionalPanelTools.FrameMap;
import us.ihmc.simulationconstructionset.util.RegularExpression;
import us.ihmc.yoVariables.buffer.YoBuffer;
import us.ihmc.yoVariables.buffer.YoBufferVariableEntry;
import us.ihmc.yoVariables.variable.YoDouble;
import us.ihmc.yoVariables.variable.YoVariable;

public class YoVariableSearchPanel extends JPanel implements ChangeListener
{
   private static final long serialVersionUID = -3986327052893068969L;
   private static final int SCROLL_PANE_INCREMENT = 12;
   private static final boolean USE_BOOKMARKS_PANEL = false;

   private VariableSearchBox variableSearchBox;
   private final YoBuffer dataBuffer;
   private YoVariableListPanel yoVariableSearchResultsPanel;
   private final JTextArea entryBoxDescriptionArea;
   private final YoEntryBox entryBox;
   private final SelectedVariableHolder holder;
   private JLabel label;

   private GridBagConstraints frameLabelConstraint;
   private FrameMap frameMap;
   private Predicate filter;
   private final JLabel frameLabel = new JLabel();

   private boolean showOnlyParameters = false;

   public YoVariableSearchPanel(SelectedVariableHolder holder, YoBuffer dataBuffer, GraphArrayPanel graphArrayPanel,
                                EntryBoxArrayTabbedPanel entryBoxArrayPanel, BookmarkedVariablesHolder bookmarkedVariablesHolder,
                                YoVariableExplorerTabbedPane combinedVarPanel)
   {
      super(new BorderLayout());

      setName("SearchPanel");

      if (bookmarkedVariablesHolder == null)
      {
         System.err.println("Error: Bookmarks panel null!");
      }

      // Setup a scroll panel for the VarPanel, then add it to the center of the display
      yoVariableSearchResultsPanel = new YoVariableListPanel("Search",
                                                             holder,
                                                             new YoVariablePanelJPopupMenu(graphArrayPanel,
                                                                                           entryBoxArrayPanel,
                                                                                           holder,
                                                                                           combinedVarPanel,
                                                                                           bookmarkedVariablesHolder),
                                                             this);
      this.holder = yoVariableSearchResultsPanel.getVariableHolder();
      this.holder.addChangeListener(this);

      JScrollPane searchResultScrollPane = new JScrollPane(yoVariableSearchResultsPanel,
                                                           ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
                                                           ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
      searchResultScrollPane.getVerticalScrollBar().setUnitIncrement(SCROLL_PANE_INCREMENT);
      searchResultScrollPane.getVerticalScrollBar().setBlockIncrement(SCROLL_PANE_INCREMENT);
      searchResultScrollPane.setPreferredSize(new Dimension(60, 260));
      searchResultScrollPane.setBorder(new EtchedBorder());

      JSplitPane splitPane = null;
      if (USE_BOOKMARKS_PANEL)
      {
         BookmarkedVariablesPanel bookmarkedVariablesPanel = new BookmarkedVariablesPanel("Bookmarks",
                                                                                          yoVariableSearchResultsPanel.selectedVariableHolder,
                                                                                          bookmarkedVariablesHolder);
         JScrollPane bookMarkScrollPane = new JScrollPane(bookmarkedVariablesPanel,
                                                          ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
                                                          ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
         bookMarkScrollPane.getVerticalScrollBar().setUnitIncrement(SCROLL_PANE_INCREMENT);
         bookMarkScrollPane.getVerticalScrollBar().setBlockIncrement(SCROLL_PANE_INCREMENT);
         bookMarkScrollPane.setPreferredSize(new Dimension(60, 40));
         bookMarkScrollPane.setBorder(new EtchedBorder());

         splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, searchResultScrollPane, bookMarkScrollPane);
         splitPane.setResizeWeight(1);
         splitPane.setBorder(null);
         splitPane.setDividerSize(3);
         splitPane.setDividerLocation(200);
      }

      // Setup the description panel & YoEntryBox deal
      entryBox = new YoEntryBox(null, holder);

      // Setup a JTextArea to display the description and configure it
      // to word wrap
      entryBoxDescriptionArea = new JTextArea();
      entryBoxDescriptionArea.setEditable(false);
      entryBoxDescriptionArea.setLineWrap(true);
      entryBoxDescriptionArea.setWrapStyleWord(true);
      entryBoxDescriptionArea.setVisible(true);

      JScrollPane descrScroll = new JScrollPane(entryBoxDescriptionArea);
      descrScroll.setVisible(true);

      //    descrPanel.add(entryBox, BorderLayout.NORTH);
      //    descrPanel.add(descrScroll, BorderLayout.CENTER);
      //    descrPanel.setMinimumSize(new Dimension(10, 10));
      //    descrPanel.setPreferredSize(new Dimension(10, 10));
      //    descrPanel.setVisible(false);

      label = new JLabel("Search Settings:");
      label.setAlignmentX(CENTER_ALIGNMENT);

      JLabel varDescription = new JLabel("");
      label.setAlignmentX(CENTER_ALIGNMENT);

      this.add(entryBox, BorderLayout.SOUTH);
      this.add(varDescription, BorderLayout.SOUTH);
      this.add(label, BorderLayout.SOUTH);

      this.dataBuffer = dataBuffer;
      setLayout(new GridBagLayout());
      removeAll();
      GridBagConstraints c = new GridBagConstraints();

      c.fill = GridBagConstraints.HORIZONTAL;
      c.anchor = GridBagConstraints.NORTH;
      c.weightx = 1.0;
      c.weighty = 0.0;
      c.gridx = 0;
      c.gridy = 0;
      c.gridheight = 1;
      c.gridwidth = 1;

      variableSearchBox = new VariableSearchBox();
      c.gridy++;
      c.gridwidth = 6;
      this.add(variableSearchBox, c);

      c.weighty = 1.0;
      c.gridx = 0;
      c.gridy++;
      c.fill = GridBagConstraints.BOTH;
      c.gridwidth = 6;
      c.gridheight = 5;
      if (USE_BOOKMARKS_PANEL)
      {
         this.add(splitPane, c);
      }
      else
      {
         this.add(searchResultScrollPane, c);
      }

      c.weighty = 0.0;
      c.gridy += 5;
      c.gridheight = 1;
      c.fill = GridBagConstraints.HORIZONTAL;
      this.add(entryBox, c);

      frameLabel.setBorder(new EmptyBorder(0, 6, 0, 6));
      frameLabelConstraint = new GridBagConstraints();
      frameLabelConstraint.anchor = c.anchor;
      frameLabelConstraint.fill = c.fill;
      frameLabelConstraint.weightx = c.weightx;
      frameLabelConstraint.weighty = c.weighty;
      frameLabelConstraint.gridx = c.gridx;
      frameLabelConstraint.gridy = c.gridy + 1;
      frameLabelConstraint.gridwidth = c.gridwidth;
      frameLabelConstraint.gridheight = c.gridheight;
      holder.addChangeListener(e -> updateFrameLabel());
   }

   public void updateFrameLabel()
   {
      if (frameMap == null || filter == null)
      {
         return;
      }

      YoVariable yoVariable = holder.getSelectedVariable();
      if (filter.test(yoVariable))
      {
         ReferenceFrame frame = frameMap.getReferenceFrame(yoVariable.getValueAsLongBits());
         if (frame != null)
         {
            frameLabel.setText(frame.getName());
         }
         else
         {
            frameLabel.setText("UNKNOWN");
         }
         add(frameLabel, frameLabelConstraint);
      }
      else
      {
         remove(frameLabel);
      }
   }

   public void setFrameMap(FrameMap frameMap, Predicate filter)
   {
      this.frameMap = frameMap;
      this.filter = filter;
   }

   public void setDoubleClickListener(DoubleClickListener listener)
   {
      yoVariableSearchResultsPanel.setDoubleClickListener(listener);
   }

   @Override
   public void paintComponent(Graphics g)
   {
      super.paintComponent(g);
      entryBox.updateActiveContainer();
   }

   public void setShowOnlyParameters(boolean showOnlyParameters)
   {
      if (this.showOnlyParameters != showOnlyParameters)
      {
         this.showOnlyParameters = showOnlyParameters;

         SwingUtilities.invokeLater(() ->
         {
            if (variableSearchBox.hasSearched())
            {
               variableSearchBox.findMatchingVariablesRegularExpression();
            }
         });
      }
   }

   @Override
   public void stateChanged(ChangeEvent e)
   {
      Runnable entryBoxChanger = new Runnable()
      {
         @Override
         public void run()
         {
            YoVariable selectedVariable = holder.getSelectedVariable();
            if (selectedVariable != null)
            {
               entryBox.addVariable(selectedVariable);
               entryBoxDescriptionArea.setText(selectedVariable.getDescription());
               entryBoxDescriptionArea.setCaretPosition(0);
            }
            else
            {
               entryBox.addVariable(new YoDouble("null", null));
               entryBoxDescriptionArea.setText("");
            }
         }
      };

      SwingUtilities.invokeLater(entryBoxChanger); // so that we don't interfere with paintComponent
   }

   public class VariableSearchBox extends JPanel implements ActionListener
   {
      private static final long serialVersionUID = 2584008799193548359L;
      private final JTextField searchTextField;
      private final Executor searchExecutor = Executors.newSingleThreadExecutor();
      private Searcher searcher;
      private boolean searched = false;

      public VariableSearchBox()
      {
         setLayout(new GridLayout(1, 1));
         searchTextField = new JTextField();
         searchTextField.setName("SearchTextField");

         searchTextField.addActionListener(this);
         String s = "Search Tips :
" + "A * B = starting with 'A' and ending with 'B'
" + "A* = starting with 'A'
" + "*A = ending with 'A'
" + "\"A\" = exactly 'A'
" + "A* | B* anything starting with 'A' or 'B'
"; searchTextField.setToolTipText(s); DocumentListener documentListener = new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { findMatchingVariablesRegularExpression(); } @Override public void removeUpdate(DocumentEvent e) { findMatchingVariablesRegularExpression(); } @Override public void changedUpdate(DocumentEvent e) { } }; searchTextField.getDocument().addDocumentListener(documentListener); this.add(searchTextField); } public boolean hasSearched() { return searched; } @Override public void actionPerformed(ActionEvent e) { findMatchingVariablesRegularExpression(); } public void findMatchingVariablesRegularExpression() { searched = true; if (searcher != null) { searcher.stopSearch(); } searcher = new Searcher(searchTextField.getText().toString()); searchExecutor.execute(searcher); } public class Searcher implements Runnable { private String searchText; private boolean stopSearch = false; private ArrayList startsWithSearchTextList = new ArrayList<>(); private ArrayList doesNotStartWithSearchTextList = new ArrayList<>(); public Searcher(String searchText) { this.searchText = searchText; } @Override public void run() { final List matchedVariables = search(searchText); if (!stopSearch) yoVariableSearchResultsPanel.removeAllVariables(); if (matchedVariables != null) { for (YoVariable variable : matchedVariables) { if (stopSearch) break; yoVariableSearchResultsPanel.addVariable(variable); } } } public List search(String searchText) { List ret = new ArrayList<>(); List entries = dataBuffer.getEntries(); for (int i = 0; i < entries.size(); i++) { if (stopSearch) { return null; } YoBufferVariableEntry entry = entries.get(i); boolean match = RegularExpression.check(entry.getVariable().getName(), searchText); if (match && showOnlyParameters) { match = entry.getVariable().isParameter(); } if (match) { ret.add(entry.getVariable()); } } sortList(ret); return ret; } // display matches in the order: exact, starts with, rest private void sortList(List list) { YoVariable temporaryYoVariable; String searchTextLowerCase = searchText.toLowerCase(); for (int i = 0; i < list.size(); i++) { if ((list.get(i).getName().length() >= searchText.length()) && searchTextLowerCase.equals(list.get(i).getName().substring(0, searchText.length()))) { startsWithSearchTextList.add(list.get(i)); } else { doesNotStartWithSearchTextList.add(list.get(i)); } } if (startsWithSearchTextList != null) { for (int i = 0; i < startsWithSearchTextList.size(); i++) { if (searchTextLowerCase.equals(startsWithSearchTextList.get(i).getName().toLowerCase())) { temporaryYoVariable = startsWithSearchTextList.get(i); startsWithSearchTextList.set(i, startsWithSearchTextList.get(0)); startsWithSearchTextList.set(0, temporaryYoVariable); } } for (int i = 0; i < doesNotStartWithSearchTextList.size(); i++) { startsWithSearchTextList.add(doesNotStartWithSearchTextList.get(i)); } } list.clear(); for (int i = 0; i < startsWithSearchTextList.size(); i++) { list.add(startsWithSearchTextList.get(i)); } } public void stopSearch() { stopSearch = true; } } } public void refreshSearchPanelWidth() { yoVariableSearchResultsPanel.refreshPanelWidth(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy