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

us.ihmc.scs2.sessionVisualizer.jfx.controllers.yoGraphic.YoGraphicPropertyWindowController Maven / Gradle / Ivy

package us.ihmc.scs2.sessionVisualizer.jfx.controllers.yoGraphic;

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.SetChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBoxTreeItem;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.input.Dragboard;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
import javafx.util.Duration;
import org.controlsfx.control.CheckTreeView;
import org.kordamp.ikonli.javafx.FontIcon;
import us.ihmc.messager.javafx.JavaFXMessager;
import us.ihmc.scs2.sessionVisualizer.jfx.SessionVisualizerIOTools;
import us.ihmc.scs2.sessionVisualizer.jfx.SessionVisualizerTopics;
import us.ihmc.scs2.sessionVisualizer.jfx.controllers.yoComposite.search.SearchEngines;
import us.ihmc.scs2.sessionVisualizer.jfx.managers.BackgroundExecutorManager;
import us.ihmc.scs2.sessionVisualizer.jfx.managers.SessionVisualizerToolkit;
import us.ihmc.scs2.sessionVisualizer.jfx.tools.DragAndDropTools;
import us.ihmc.scs2.sessionVisualizer.jfx.tools.JavaFXMissingTools;
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.scs2.sessionVisualizer.jfx.yoGraphic.YoGraphicFX;
import us.ihmc.scs2.sessionVisualizer.jfx.yoGraphic.YoGraphicFX2D;
import us.ihmc.scs2.sessionVisualizer.jfx.yoGraphic.YoGraphicFX3D;
import us.ihmc.scs2.sessionVisualizer.jfx.yoGraphic.YoGraphicFXItem;
import us.ihmc.scs2.sessionVisualizer.jfx.yoGraphic.YoGroupFX;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

public class YoGraphicPropertyWindowController extends ObservedAnimationTimer
{
   @FXML
   private AnchorPane mainAnchorPane;
   @FXML
   private CheckTreeView yoGraphicTreeView;
   @FXML
   private Button addItemButton, removeItemButton;
   @FXML
   private TextField searchTextField;
   @FXML
   private Label yoGraphicTypeLabel;
   @FXML
   private AnchorPane yoGraphicEditorPane;
   @FXML
   private Button saveChangesButton, revertChangesButton;

   private CheckBoxTreeItem defaultRootItem;

   private CheckBoxTreeItem searchResult = null;
   private List allGraphicItems;
   private Future> backgroundSearch;
   private BackgroundExecutorManager backgroundExecutorManager;

   private SessionVisualizerToolkit toolkit;
   private SessionVisualizerTopics topics;
   private JavaFXMessager messager;
   private final ObjectProperty cachedItemCreator = new SimpleObjectProperty<>(this, "cachedItemCreator", null);
   private final ObjectProperty> activeEditor = new SimpleObjectProperty<>(this, "activeEditor", null);
   private final Map> cachedEditors = new HashMap<>();
   private final ObjectProperty activeContexMenu = new SimpleObjectProperty<>(this, "activeContextMenu", null);
   private YoGroupFX rootGroup;
   private YoGroupFX sessionRootGroup;
   private Stage window;

   public void initialize(SessionVisualizerToolkit toolkit)
   {
      this.toolkit = toolkit;
      topics = toolkit.getTopics();
      messager = toolkit.getMessager();
      rootGroup = toolkit.getYoGraphicFXRootGroup();
      sessionRootGroup = toolkit.getYoGraphicFXSessionRootGroup();
      backgroundExecutorManager = toolkit.getBackgroundExecutorManager();

      initializeTreeViewAutoRefreshListener(rootGroup);

      yoGraphicTreeView.setCellFactory(param -> new YoGraphicFXItemTreeCell(rootGroup));
      yoGraphicTreeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
      yoGraphicTreeView.getSelectionModel()
                       .selectedItemProperty()
                       .addListener((observable, oldValue, newValue) -> processTreeSelectionUpdate(oldValue, newValue));
      yoGraphicTreeView.setShowRoot(true);
      yoGraphicTreeView.setOnDragDetected(this::handleDragDetected);
      yoGraphicTreeView.addEventHandler(KeyEvent.KEY_PRESSED, e ->
      {
         if (e.getCode() == KeyCode.DELETE)
            removeItem();
      });
      yoGraphicTreeView.setOnContextMenuRequested(e ->
                                                  {
                                                     if (activeContexMenu.get() != null)
                                                     {
                                                        activeContexMenu.get().hide();
                                                        activeContexMenu.set(null);
                                                     }

                                                     FontIcon collapseIcon = new FontIcon("fa-minus-square-o");
                                                     FontIcon expandIcon = new FontIcon("fa-plus-square-o");
                                                     FontIcon addIcon = new FontIcon("fa-plus");
                                                     FontIcon deleteIcon = new FontIcon("fa-times");
                                                     FontIcon duplicateIcon = new FontIcon("fa-clone");
                                                     addIcon.setFill(Color.web("#89e0c0"));
                                                     deleteIcon.setFill(Color.web("#edafb7"));
                                                     duplicateIcon.setFill(Color.web("#8996e0"));
                                                     MenuItem collapseItem = new MenuItem("Collapse all", collapseIcon);
                                                     MenuItem expandItem = new MenuItem("Expand all", expandIcon);
                                                     MenuItem addItem = new MenuItem("Add item...", addIcon);
                                                     MenuItem removeItem = new MenuItem("Remove item", deleteIcon);
                                                     MenuItem duplicateItem = new MenuItem("Duplicate item", duplicateIcon);
                                                     collapseItem.setOnAction(e2 -> collapseAll());
                                                     expandItem.setOnAction(e2 -> expandAll());
                                                     addItem.setOnAction(e2 -> addItem());
                                                     removeItem.setOnAction(e2 -> removeItem());
                                                     duplicateItem.setOnAction(e2 -> duplicateItem());

                                                     ContextMenu contextMenu = new ContextMenu(collapseItem, expandItem, addItem, removeItem, duplicateItem);
                                                     contextMenu.show(yoGraphicTreeView, e.getScreenX(), e.getScreenY());
                                                     activeContexMenu.set(contextMenu);
                                                  });
      refreshTreeView();

      saveChangesButton.setDisable(true);
      revertChangesButton.setDisable(true);

      activeEditor.addListener((observable, oldValue, newValue) ->
                               {
                                  saveChangesButton.disableProperty().unbind();
                                  revertChangesButton.disableProperty().unbind();

                                  if (newValue == null)
                                  {
                                     saveChangesButton.setDisable(true);
                                     revertChangesButton.setDisable(true);
                                  }
                                  else
                                  {
                                     saveChangesButton.disableProperty()
                                                      .bind(newValue.hasChangesPendingProperty().and(newValue.inputsValidityProperty()).not());
                                     revertChangesButton.disableProperty().bind(newValue.hasChangesPendingProperty().not());
                                     newValue.saveChanges();
                                     newValue.resetFields();
                                  }
                               });

      yoGraphicEditorPane.addEventHandler(KeyEvent.KEY_PRESSED, e ->
      {
         if (e.getCode() == KeyCode.CONTROL)
            return;
         if (e.isControlDown())
         {
            if (e.getCode() == KeyCode.S && !saveChangesButton.isDisabled())
            {
               saveChangesButton.fire();
            }
            else if (e.getCode() == KeyCode.Z && !revertChangesButton.isDisabled())
            {
               revertChangesButton.fire();
            }
         }
      });

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

      window = new Stage(StageStyle.UTILITY);
      window.addEventHandler(KeyEvent.KEY_PRESSED, e ->
      {
         if (e.getCode() == KeyCode.ESCAPE)
            window.close();
      });
      toolkit.getMainWindow().addEventFilter(WindowEvent.WINDOW_CLOSE_REQUEST, e ->
      {
         if (!e.isConsumed())
            window.close();
      });
      window.setOnHidden(e -> stop());
      window.setOnShowing(e -> start());
      window.setTitle("YoGraphic properties");
      window.setScene(new Scene(mainAnchorPane));
      window.initOwner(toolkit.getMainWindow());
   }

   public void showWindow()
   {
      window.setOpacity(0.0);
      window.toFront();
      window.show();
      Timeline timeline = new Timeline();
      KeyFrame key = new KeyFrame(Duration.seconds(0.125), new KeyValue(window.opacityProperty(), 1.0));
      timeline.getKeyFrames().add(key);
      timeline.play();
   }

   public void closeAndDispose()
   {
      window.close();
   }

   private final SetChangeListener treeViewAutoRefreshListener = new SetChangeListener()
   {
      @Override
      public void onChanged(Change change)
      {
         if (change.wasAdded())
         {
            change.getElementAdded().getItemChildren().addListener(treeViewAutoRefreshListener);
         }
         else if (change.wasRemoved())
         {
            change.getElementRemoved().getItemChildren().removeListener(treeViewAutoRefreshListener);
         }

         JavaFXMissingTools.runLater(getClass(), () ->
         {
            ignoreTreeSelectionUpdate = true;
            refreshTreeView();
            ignoreTreeSelectionUpdate = false;
         });
      }
   };

   private void initializeTreeViewAutoRefreshListener(YoGraphicFXItem item)
   {
      item.getItemChildren().addListener(treeViewAutoRefreshListener);

      for (YoGraphicFXItem child : item.getItemChildren())
         initializeTreeViewAutoRefreshListener(child);
   }

   private void refreshTreeView()
   {
      unloadEditor();
      CheckBoxTreeItem oldRootItem = defaultRootItem;
      defaultRootItem = new CheckBoxTreeItem<>(rootGroup);
      defaultRootItem.setExpanded(true);
      defaultRootItem.selectedProperty().bindBidirectional(defaultRootItem.getValue().visibleProperty());
      buildTreeRecursively(defaultRootItem);
      yoGraphicTreeView.setRoot(defaultRootItem);
      copyExpandedPropertyRecursively(oldRootItem, defaultRootItem);
      allGraphicItems = rootGroup.collectSubtreeItems();
   }

   private void copyExpandedPropertyRecursively(TreeItem reference, TreeItem item)
   {
      if (item != null && !item.isLeaf())
      {
         for (TreeItem child : item.getChildren())
         {
            if (reference == null)
            {
               TreeViewTools.expandRecursively(child);
            }
            else
            {
               TreeItem referenceChild = reference.getChildren()
                                                     .stream()
                                                     .filter(refChild -> refChild.getValue() == child.getValue())
                                                     .findFirst()
                                                     .orElse(null);
               if (referenceChild == null)
               {
                  TreeViewTools.expandRecursively(child);
               }
               else
               {
                  child.setExpanded(referenceChild.isExpanded());
                  copyExpandedPropertyRecursively(referenceChild, child);
               }
            }
         }
      }
   }

   private TreeItem selectItem(TreeItem treeItem, YoGraphicFXItem itemToSelect)
   {
      if (treeItem == null)
         return null;
      if (treeItem.getValue() == itemToSelect)
      {
         yoGraphicTreeView.getSelectionModel().select(treeItem);
         return treeItem;
      }

      for (TreeItem child : treeItem.getChildren())
      {
         if (selectItem(child, itemToSelect) != null)
            return child;
      }
      return null;
   }

   private boolean ignoreTreeSelectionUpdate = false;

   private void processTreeSelectionUpdate(TreeItem oldSelectedValue, TreeItem newSelectedValue)
   {
      if (ignoreTreeSelectionUpdate)
         return;

      if (shouldCancelAction(oldSelectedValue))
         return;

      unloadEditor();

      if (newSelectedValue == null)
         return;

      YoGraphicFXItem item = newSelectedValue.getValue();

      Class itemType = item.getClass();

      YoGraphicFXCreatorController controller = cachedEditors.get(item);

      if (controller == null)
      {
         try
         {
            if (item instanceof YoGroupFX)
            {
               Class commonItemType = findCommonChildrenType((YoGroupFX) item);
               if (commonItemType == null)
                  return;

               FXMLLoader loader = SessionVisualizerIOTools.getYoGraphicFXGroupEditorFXMLLoader(commonItemType);
               loader.load();
               controller = loader.getController();
               controller.initialize(toolkit, (YoGraphicFXItem) item);
               cachedEditors.put(item, controller);
            }
            else
            {
               FXMLLoader loader = SessionVisualizerIOTools.getYoGraphicFXEditorFXMLLoader(itemType);
               loader.load();
               controller = loader.getController();
               controller.initialize(toolkit, (YoGraphicFXItem) item);
               cachedEditors.put(item, controller);
            }
         }
         catch (IOException e)
         {
            e.printStackTrace();
         }
      }

      if (controller != null)
      {
         Pane editorPane = controller.getMainPane();
         activeEditor.set(controller);
         yoGraphicEditorPane.getChildren().add(editorPane);
         AnchorPane.setLeftAnchor(editorPane, 0.0);
         AnchorPane.setRightAnchor(editorPane, 0.0);
         AnchorPane.setTopAnchor(editorPane, 0.0);
         AnchorPane.setBottomAnchor(editorPane, 0.0);
         yoGraphicTypeLabel.setText(itemType.getSimpleName());
      }
   }

   private static Class findCommonChildrenType(YoGroupFX group)
   {
      if (!group.getYoGraphicFX2DSet().isEmpty())
      {
         if (!group.getYoGraphicFX3DSet().isEmpty())
            return null;

         Class commonType = null;

         for (YoGraphicFX2D item : group.getYoGraphicFX2DSet())
         {
            if (commonType == null)
               commonType = item.getClass();
            else if (commonType != item.getClass())
               return null;
         }

         return commonType;
      }
      else if (!group.getYoGraphicFX3DSet().isEmpty())
      {

         Class commonType = null;

         for (YoGraphicFX3D item : group.getYoGraphicFX3DSet())
         {
            if (commonType == null)
               commonType = item.getClass();
            else if (commonType != item.getClass())
               return null;
         }

         return commonType;
      }
      else
      {
         return null;
      }
   }

   private void unloadEditor()
   {
      yoGraphicEditorPane.getChildren().clear();
      activeEditor.set(null);
   }

   @FXML
   public void clearSearch()
   {
      searchTextField.clear();
   }

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

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

                                                                             return createFilteredRootItem(YoVariableTools.search(allGraphicItems,
                                                                                                                                  item -> item.getName(),
                                                                                                                                  searchQuery,
                                                                                                                                  YoVariableTools.fromSearchEnginesEnum(
                                                                                                                                        SearchEngines.DEFAULT),
                                                                                                                                  Integer.MAX_VALUE,
                                                                                                                                  Collectors.toSet()));
                                                                          });
      }
      else
      {
         searchResult = defaultRootItem;
         expandAll();
      }
   }

   private CheckBoxTreeItem createFilteredRootItem(Set subSelection)
   {
      CheckBoxTreeItem root = new CheckBoxTreeItem<>(rootGroup);
      buildTreeRecursively(root);
      filterItems(root, subSelection);
      TreeViewTools.expandRecursively(root);
      return root;
   }

   private static void filterItems(TreeItem parent, Set itemsToKeep)
   {
      filterItems(parent, itemsToKeep.contains(parent.getValue()), itemsToKeep);
   }

   private static void filterItems(TreeItem parent, boolean isAncestorInSelection, Set itemsToKeep)
   {
      if (parent == null || parent.isLeaf())
         return;

      for (TreeItem child : parent.getChildren())
      {
         if (!child.getChildren().isEmpty())
            filterItems(child, isAncestorInSelection || itemsToKeep.contains(child.getValue()), itemsToKeep);
      }

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

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

         if (!isAncestorInSelection && !itemsToKeep.contains(child.getValue()))
            parent.getChildren().remove(i);
      }
   }

   @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)
      {
         yoGraphicTreeView.setRoot(searchResult);
         searchResult = null;
      }
   }

   public void collapseAll()
   {
      TreeViewTools.collapseRecursively(yoGraphicTreeView.getRoot());
   }

   public void expandAll()
   {
      TreeViewTools.expandRecursively(yoGraphicTreeView.getRoot());
   }

   @FXML
   public void addItem()
   {
      if (shouldCancelAction(null))
         return;

      TreeItem selectedItem = yoGraphicTreeView.getSelectionModel().getSelectedItem();
      YoGroupFX group;

      if (selectedItem == null)
      {
         group = rootGroup;
      }
      else
      {
         YoGraphicFXItem yoGraphicFXItem = selectedItem.getValue();

         if (yoGraphicFXItem instanceof YoGraphicFX)
            group = yoGraphicFXItem.parentGroupProperty().get();
         else if (yoGraphicFXItem instanceof YoGroupFX)
            group = ((YoGroupFX) yoGraphicFXItem);
         else
            throw new RuntimeException("Unexpected item type: " + yoGraphicFXItem.getClass().getSimpleName());
      }

      try
      {
         if (cachedItemCreator.get() == null)
         {
            FXMLLoader loader = new FXMLLoader(SessionVisualizerIOTools.YO_GRAPHIC_ITEM_CREATOR_URL);
            loader.load();
            YoGraphicItemCreatorDialogController controller = loader.getController();
            controller.initialize(toolkit);
            cachedItemCreator.set(controller);
         }

         YoGraphicItemCreatorDialogController controller = cachedItemCreator.get();
         controller.setParent(group);
         controller.showAndWait();

         YoGraphicFXItem newItem = controller.createItem();

         if (newItem != null)
         {
            JavaFXMissingTools.runLater(getClass(), () ->
            {
               TreeItem newTreeItem = selectItem(defaultRootItem, newItem);
               yoGraphicTreeView.requestFocus();
               if (newTreeItem != null)
                  yoGraphicTreeView.scrollTo(yoGraphicTreeView.getRow(newTreeItem));
            });
         }
      }
      catch (IOException e)
      {
         e.printStackTrace();
      }
   }

   @FXML
   public void removeItem()
   {
      if (shouldCancelAction(null))
         return;

      TreeItem selectedItem = yoGraphicTreeView.getSelectionModel().getSelectedItem();

      if (selectedItem == null || selectedItem.getValue().parentGroupProperty() == null)
         return;

      int selectedIndex = yoGraphicTreeView.getSelectionModel().getSelectedIndex();
      ObservableList> itemsToRemove = yoGraphicTreeView.getSelectionModel().getSelectedItems();

      int nextSelectedIndexGuess = selectedIndex - 1;
      TreeItem nextSelectedItemGuess = yoGraphicTreeView.getTreeItem(nextSelectedIndexGuess);

      if (nextSelectedItemGuess == null || itemsToRemove.contains(nextSelectedItemGuess))
      {
         nextSelectedIndexGuess = selectedIndex + 1;
         nextSelectedItemGuess = yoGraphicTreeView.getTreeItem(nextSelectedIndexGuess);

         if (nextSelectedItemGuess == null || itemsToRemove.contains(nextSelectedItemGuess))
         {
            nextSelectedIndexGuess = selectedIndex - 1;
            nextSelectedItemGuess = yoGraphicTreeView.getTreeItem(nextSelectedIndexGuess);

            do
            {
               nextSelectedIndexGuess--;
               if (nextSelectedIndexGuess < 0)
               {
                  nextSelectedItemGuess = null;
                  nextSelectedIndexGuess = 0;
                  break;
               }
               nextSelectedItemGuess = yoGraphicTreeView.getTreeItem(nextSelectedIndexGuess);
            }
            while (nextSelectedItemGuess == null || itemsToRemove.contains(nextSelectedItemGuess));
         }
      }

      YoGraphicFXItem nextSelectedItem = nextSelectedItemGuess == null ? null : nextSelectedItemGuess.getValue();

      for (TreeItem itemToRemove : itemsToRemove)
      {
         YoGraphicFXItem yoGraphicFXItem = itemToRemove.getValue();

         if (!yoGraphicFXItem.getItemChildren().isEmpty())
         {
            Alert alert = new Alert(AlertType.CONFIRMATION);
            alert.setContentText("Do you really want to delete this group and all its children?");
            alert.initOwner(window);
            ButtonType answer = alert.showAndWait().get();
            if (answer.getButtonData().isCancelButton())
               return;
         }

         yoGraphicFXItem.clear();

         if (yoGraphicFXItem != sessionRootGroup)
            yoGraphicFXItem.detachFromParent();
      }

      cachedEditors.remove(selectedItem.getValue());

      JavaFXMissingTools.runLater(getClass(), () ->
      {
         ignoreTreeSelectionUpdate = true;
         yoGraphicTreeView.getSelectionModel().clearSelection();
         ignoreTreeSelectionUpdate = false;
         if (nextSelectedItem == null)
            yoGraphicTreeView.getSelectionModel().select(0);
         else
            selectItem(defaultRootItem, nextSelectedItem);
         yoGraphicTreeView.requestFocus();
      });
   }

   public void duplicateItem()
   {
      if (shouldCancelAction(null))
         return;

      TreeItem selectedItem = yoGraphicTreeView.getSelectionModel().getSelectedItem();

      if (selectedItem == null)
         return;

      YoGraphicFXItem newItem = YoGraphicFXControllerTools.duplicateYoGraphicFXItemAndRegister(selectedItem.getValue());

      JavaFXMissingTools.runLater(getClass(), () ->
      {
         selectItem(defaultRootItem, newItem);
         yoGraphicTreeView.requestFocus();
      });
   }

   @FXML
   public void saveChanges()
   {
      if (activeEditor.get() != null)
         activeEditor.get().saveChanges();
   }

   @FXML
   public void cancelChanges()
   {
      if (activeEditor.get() != null)
         activeEditor.get().resetFields();
   }

   @FXML
   public void exportYoGraphicFXItems()
   {
      File result = SessionVisualizerIOTools.yoGraphicConfigurationSaveFileDialog(window);
      if (result != null)
         messager.submitMessage(topics.getYoGraphicSaveRequest(), result);
   }

   @FXML
   public void importYoGraphicFXItems()
   {
      File result = SessionVisualizerIOTools.yoGraphicConfigurationOpenFileDialog(window);
      if (result != null)
         messager.submitMessage(topics.getYoGraphicLoadRequest(), result);
   }

   public Stage getWindow()
   {
      return window;
   }

   private boolean shouldCancelAction(TreeItem itemToSelectOnCancel)
   {
      if (activeEditor.get() != null && activeEditor.get().hasChangesPending())
      {
         Alert alert = new Alert(AlertType.CONFIRMATION, "Do you want to discard the changes?", ButtonType.YES, ButtonType.NO);
         SessionVisualizerIOTools.addSCSIconToDialog(alert);
         Optional result = alert.showAndWait();
         ButtonType answer = result.get();

         if (answer == ButtonType.YES)
         {
            cancelChanges();
            return false;
         }
         else if (answer == ButtonType.NO)
         {
            if (itemToSelectOnCancel != null)
            {
               JavaFXMissingTools.runLater(getClass(), () ->
               {
                  ignoreTreeSelectionUpdate = true;
                  yoGraphicTreeView.getSelectionModel().clearSelection();
                  yoGraphicTreeView.getSelectionModel().select(itemToSelectOnCancel);
                  ignoreTreeSelectionUpdate = false;
               });
            }
            return true;
         }
      }

      return false;
   }

   private void buildTreeRecursively(TreeItem parent)
   {
      for (YoGraphicFXItem child : parent.getValue().getItemChildren())
      {
         CheckBoxTreeItem childItem = new CheckBoxTreeItem<>(child);
         childItem.setIndependent(true);
         childItem.selectedProperty().bindBidirectional(childItem.getValue().visibleProperty());
         parent.getChildren().add(childItem);
         buildTreeRecursively(childItem);
      }
   }

   public void handleDragDetected(MouseEvent event)
   {
      List items = yoGraphicTreeView.getSelectionModel()
                                                     .getSelectedItems()
                                                     .stream()
                                                     .map(TreeItem::getValue)
                                                     .collect(Collectors.toList());

      Dragboard dragBoard = yoGraphicTreeView.startDragAndDrop(TransferMode.ANY);
      dragBoard.setContent(DragAndDropTools.toClipboardContent(items));
      event.consume();
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy