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

us.ihmc.scs2.sessionVisualizer.jfx.controllers.yoComposite.search.YoRegistrySearchPaneController Maven / Gradle / Ivy

package us.ihmc.scs2.sessionVisualizer.jfx.controllers.yoComposite.search;

import javafx.beans.property.Property;
import javafx.fxml.FXML;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.input.*;
import us.ihmc.messager.javafx.JavaFXMessager;
import us.ihmc.scs2.session.Session;
import us.ihmc.scs2.session.SessionState;
import us.ihmc.scs2.sessionVisualizer.jfx.SessionVisualizerTopics;
import us.ihmc.scs2.sessionVisualizer.jfx.managers.BackgroundExecutorManager;
import us.ihmc.scs2.sessionVisualizer.jfx.managers.SecondaryWindowManager.NewWindowRequest;
import us.ihmc.scs2.sessionVisualizer.jfx.managers.SessionVisualizerToolkit;
import us.ihmc.scs2.sessionVisualizer.jfx.managers.YoManager;
import us.ihmc.scs2.sessionVisualizer.jfx.tools.MenuTools;
import us.ihmc.scs2.sessionVisualizer.jfx.tools.ObservedAnimationTimer;
import us.ihmc.scs2.sessionVisualizer.jfx.tools.TreeViewTools;
import us.ihmc.scs2.sessionVisualizer.jfx.tools.YoVariableTools;
import us.ihmc.yoVariables.registry.YoRegistry;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class YoRegistrySearchPaneController extends ObservedAnimationTimer
{
   @FXML
   private TextField searchTextField;

   @FXML
   private TreeView registryTreeView;

   private List allRegistries;

   private TreeItem defaultRootItem;
   private TreeItem searchResult = null;
   private boolean showRoot = true;

   private Property showSCS2YoVariables;
   private Predicate scs2InternalRegistryFilter;

   private AtomicReference activeSearchEngine;

   private YoRegistry rootRegistry;

   private Future> backgroundSearch;

   private boolean refreshRootRegistry;

   private YoManager yoManager;
   private BackgroundExecutorManager backgroundExecutorManager;

   private Consumer registryViewRequestConsumer = null;

   public void initialize(SessionVisualizerToolkit toolkit)
   {
      yoManager = toolkit.getYoManager();
      backgroundExecutorManager = toolkit.getBackgroundExecutorManager();
      registryTreeView.setCellFactory(param -> new YoRegistryTreeCell());
      registryTreeView.setRoot(defaultRootItem);
      JavaFXMessager messager = toolkit.getMessager();
      SessionVisualizerTopics topics = toolkit.getTopics();

      MenuTools.setupContextMenu(registryTreeView, treeView ->
      {
         MenuItem openStatisticsMenuItem = new MenuItem("Open statistics...");
         openStatisticsMenuItem.setOnAction(e ->
                                            {
                                               TreeItem selectedRegistry = treeView.getSelectionModel().getSelectedItem();
                                               if (selectedRegistry == null)
                                                  return;
                                               messager.submitMessage(topics.getOpenWindowRequest(),
                                                                      NewWindowRequest.registryStatisticWindow(toolkit.getMainWindow(),
                                                                                                               selectedRegistry.getValue()));
                                            });
         return openStatisticsMenuItem;
      });
      yoManager.rootRegistryChangeCounter().addListener((o, oldValue, newValue) -> refreshRootRegistry = true);

      searchTextField.textProperty().addListener((observable, oldValue, newValue) -> search(newValue));

      activeSearchEngine = messager.createInput(topics.getYoSearchEngine(), SearchEngines.DEFAULT);

      messager.addFXTopicListener(topics.getSessionCurrentState(), state ->
      {
         if (state == SessionState.ACTIVE)
         {
            refreshRootRegistry = true;
            start();
         }
         else if (state == SessionState.INACTIVE)
         {
            stop();
            searchResult = null;
            allRegistries = Collections.emptyList();
            defaultRootItem = new TreeItem<>();
            registryTreeView.setRoot(defaultRootItem);
            searchTextField.clear();
         }
      });

      showSCS2YoVariables = messager.createPropertyInput(topics.getShowSCS2YoVariables(), false);
      showSCS2YoVariables.addListener((o, oldValue, newValue) -> refreshRootRegistry = true);
      scs2InternalRegistryFilter = reg -> showSCS2YoVariables.getValue() || !reg.getNamespace().equals(Session.SESSION_INTERNAL_NAMESPACE);
   }

   public void requestFocusForSearchBox()
   {
      searchTextField.requestFocus();
   }

   public void setRegistryViewRequestConsumer(Consumer consumer)
   {
      this.registryViewRequestConsumer = consumer;
   }

   private void refreshRootRegistry()
   {
      rootRegistry = yoManager.getRootRegistry();

      if (rootRegistry == null)
      {
         refreshRootRegistry = true;
         allRegistries = null;
         defaultRootItem = null;
      }
      else
      {
         allRegistries = rootRegistry.collectSubtreeRegistries();
         defaultRootItem = new TreeItem<>(rootRegistry);
         buildTreeRecursively(defaultRootItem, scs2InternalRegistryFilter);
      }
   }

   @Override
   public void handleImpl(long now)
   {
      if (backgroundSearch != null && backgroundSearch.isDone() && !backgroundSearch.isCancelled())
      {
         try
         {
            searchResult = backgroundSearch.get();
         }
         catch (InterruptedException | ExecutionException e)
         {
            e.printStackTrace();
         }
      }

      if (searchResult != null)
      {
         registryTreeView.setShowRoot(showRoot);
         registryTreeView.setRoot(searchResult);
         searchResult = null;
      }

      if (refreshRootRegistry)
      {
         refreshRootRegistry = false;
         refreshRootRegistry();
         if (!refreshRootRegistry)
            search(searchTextField.getText());
      }
   }

   private void search(String searchQuery)
   {
      if (backgroundSearch != null)
      {
         backgroundSearch.cancel(true);
         backgroundSearch = null;
      }

      if (searchQuery != null && !searchQuery.isEmpty())
      {
         backgroundSearch = backgroundExecutorManager.executeInBackground(() ->
                                                                          {
                                                                             if (allRegistries == null)
                                                                             {
                                                                                refreshRootRegistry = true;
                                                                                return null;
                                                                             }

                                                                             return createRootItemForRegistries(YoVariableTools.search(allRegistries,
                                                                                                                                       registry -> registry.getNamespace()
                                                                                                                                                           .getName(),
                                                                                                                                       searchQuery,
                                                                                                                                       YoVariableTools.fromSearchEnginesEnum(
                                                                                                                                             activeSearchEngine.get()),
                                                                                                                                       Integer.MAX_VALUE,
                                                                                                                                       Collectors.toSet()));
                                                                          });
      }
      else
      {
         searchResult = defaultRootItem;
         showRoot = false;
      }
   }

   @FXML
   void openRegistryTab(InputEvent inputEvent)
   {
      if (registryViewRequestConsumer == null)
         return;

      boolean performOpenAction = false;

      if (inputEvent instanceof MouseEvent)
      {
         MouseEvent mouseEvent = (MouseEvent) inputEvent;
         performOpenAction = (mouseEvent.getButton() == MouseButton.PRIMARY && mouseEvent.getClickCount() == 2);
      }
      else if (inputEvent instanceof KeyEvent)
      {
         KeyEvent keyEvent = (KeyEvent) inputEvent;
         performOpenAction = keyEvent.getCode() == KeyCode.ENTER;
      }

      if (performOpenAction)
      {
         TreeItem selectedItem = registryTreeView.getSelectionModel().getSelectedItem();

         if (selectedItem != null)
         {
            registryViewRequestConsumer.accept(selectedItem.getValue());
            inputEvent.consume();
         }
      }
   }

   private TreeItem createRootItemForRegistries(Set subSelection)
   {
      TreeItem root = new TreeItem<>(rootRegistry);
      buildTreeRecursively(root, scs2InternalRegistryFilter);
      filterRegistries(root, subSelection);
      TreeViewTools.expandRecursively(root);
      return root;
   }

   private static void filterRegistries(TreeItem parent, Set registriesToKeep)
   {
      if (parent == null || parent.isLeaf())
         return;

      for (TreeItem child : parent.getChildren())
      {
         if (!child.getChildren().isEmpty())
            filterRegistries(child, registriesToKeep);
      }

      for (int i = parent.getChildren().size() - 1; i >= 0; i--)
      {
         TreeItem child = parent.getChildren().get(i);

         if (!child.isLeaf() || child.getValue() == null)
            continue;

         if (!registriesToKeep.contains(child.getValue()))
            parent.getChildren().remove(i);
      }
   }

   private static void buildTreeRecursively(TreeItem parent, Predicate registryFilter)
   {
      List children = parent.getValue().getChildren();

      for (int i = 0; i < children.size(); i++)
      {
         YoRegistry child = children.get(i);

         if (!registryFilter.test(child))
            continue;

         TreeItem childItem = new TreeItem<>(child);
         parent.getChildren().add(childItem);
         buildTreeRecursively(childItem, registryFilter);
      }
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy