From f26d892a97d71c59c681c95c9b74c2f600bd663f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Dervaux?= <stephane.dervaux@inrae.fr>
Date: Fri, 22 Mar 2024 12:17:47 +0100
Subject: [PATCH] add a copy cut paste on vocab node

---
 .../ontoView/OntologyOverviewController.java  | 114 +++++++++++++++++-
 1 file changed, 112 insertions(+), 2 deletions(-)

diff --git a/src/main/java/fr/inra/po2vocabmanager/view/ontoView/OntologyOverviewController.java b/src/main/java/fr/inra/po2vocabmanager/view/ontoView/OntologyOverviewController.java
index 98291a2a..78ead6af 100644
--- a/src/main/java/fr/inra/po2vocabmanager/view/ontoView/OntologyOverviewController.java
+++ b/src/main/java/fr/inra/po2vocabmanager/view/ontoView/OntologyOverviewController.java
@@ -61,8 +61,7 @@ import javafx.scene.control.TextField;
 import javafx.scene.control.*;
 import javafx.scene.image.Image;
 import javafx.scene.image.ImageView;
-import javafx.scene.input.Clipboard;
-import javafx.scene.input.ClipboardContent;
+import javafx.scene.input.*;
 import javafx.scene.layout.*;
 import javafx.scene.text.Text;
 import javafx.scene.text.TextFlow;
@@ -275,6 +274,117 @@ TableView<SimpleStringProperty> tableClose;
         wordFrequency = new ArrayList<>();
         vocabTree.setShowRoot(false);
         vocabTree.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {if (newValue != null) showNodeDetails(newValue);});
+        KeyCodeCombination copyKeyCodeCombination = new KeyCodeCombination(KeyCode.C, KeyCombination.CONTROL_ANY);
+        KeyCodeCombination cutKeyCodeCombination = new KeyCodeCombination(KeyCode.X, KeyCombination.CONTROL_ANY);
+        KeyCodeCombination pastKeyCodeCombination = new KeyCodeCombination(KeyCode.V, KeyCombination.CONTROL_ANY);
+
+        vocabTree.setOnKeyPressed(new EventHandler<KeyEvent>() {
+            @Override
+            public void handle(KeyEvent ke) {
+                if (copyKeyCodeCombination.match(ke) || cutKeyCodeCombination.match(ke)) {
+                    VocabConcept node = vocabTree.getSelectionModel().getSelectedItem().getValue();
+                    Clipboard cb = Clipboard.getSystemClipboard();
+                    ClipboardContent cc = new ClipboardContent();
+                    cc.putString(node.isPO2Node());
+                    cc.putUrl(node.getURI());
+                    if (copyKeyCodeCombination.match(ke)) {
+                        cc.put(DataFormat.RTF, "COPY");
+                    } else {
+                        cc.put(DataFormat.RTF, "CUT");
+                    }
+                    cb.setContent(cc);
+                }
+                if (pastKeyCodeCombination.match(ke)) {
+                    if(!mainApp.getOntologyControler().getCanEditProperty().get()) {
+                        ke.consume();
+                        return;
+                    }
+                    Clipboard cb = Clipboard.getSystemClipboard();
+                    VocabConcept node = vocabTree.getSelectionModel().getSelectedItem().getValue();
+                    if (node != null) {
+                        if(node.isPO2Node().equalsIgnoreCase(cb.getString())) {
+                            VocabConcept pasteNode = mainApp.getOntologyControler().getCurrentOntology().getNodeByURI(cb.getUrl());
+                            if (pasteNode != null) {
+                                MainApp.logger.debug("paste concept " + pasteNode.getName());
+                                VocabConcept loop = pasteNode.getNodeByURI(node.getURI());
+                                if (loop != null) {
+                                    Alert loopAlert = new Alert(Alert.AlertType.ERROR);
+                                    loopAlert.setTitle("Loop creation");
+                                    loopAlert.setHeaderText("Movement cancelled. You are creating a loop.");
+                                    loopAlert.initOwner(MainApp.primaryStage);
+                                    loopAlert.initModality(Modality.WINDOW_MODAL);
+                                    loopAlert.show();
+                                } else {
+                                    if (cb.getContent(DataFormat.RTF) == "CUT") {
+                                        HashMap<VocabConcept, CheckBox> listParent = new HashMap<>();
+                                        if (pasteNode.getFathers().size() == 1) {
+                                            CheckBox b = new CheckBox();
+                                            b.setSelected(true);
+                                            listParent.put(pasteNode.getFathers().get(0), b);
+                                        } else {
+                                            if (pasteNode.getFathers().size() > 1) {
+                                                Dialog selectParent = new Dialog();
+                                                selectParent.setTitle(pasteNode.getName() + " have multiple parents");
+                                                DialogPane dp = selectParent.getDialogPane();
+                                                VBox box = new VBox();
+                                                Label l = new Label("This concept have " + pasteNode.getFathers().size() + " parents.\nPlease select from which parents you want to move this concept.\n\n");
+                                                box.getChildren().add(l);
+                                                for (VocabConcept p : pasteNode.getFathers()) {
+                                                    CheckBox b = new CheckBox(p.getName());
+                                                    listParent.put(p, b);
+                                                    box.getChildren().add(b);
+                                                }
+                                                dp.setContent(box);
+                                                dp.getButtonTypes().addAll(ButtonType.CANCEL, ButtonType.OK);
+                                                selectParent.initOwner(MainApp.primaryStage);
+                                                Optional<ButtonType> click = selectParent.showAndWait();
+
+                                                if (click.isPresent() && click.get().getButtonData().equals(ButtonBar.ButtonData.CANCEL_CLOSE)) {
+                                                    listParent.clear();
+                                                }
+
+                                            }
+                                        }
+                                        for (Map.Entry<VocabConcept, CheckBox> en : listParent.entrySet()) {
+
+                                            if (en.getValue().isSelected() && !en.getKey().equals(node)) {
+                                                en.getKey().getSubNode().removeAll(pasteNode);
+                                                pasteNode.getFathers().remove(en.getKey());
+
+                                                if (!node.getSubNode().contains(pasteNode)) {
+                                                    node.addChildren(pasteNode);
+                                                }
+                                                if (!pasteNode.getFathers().contains(node)) {
+                                                    pasteNode.addFather(node);
+                                                }
+                                                MainApp.getOntologyControler().modified(true);
+                                            }
+
+                                        }
+                                        MainApp.getOntologyControler().refreshTree();
+                                    }
+                                    if (cb.getContent(DataFormat.RTF) == "COPY") {
+                                        node.addChildren(pasteNode);
+                                        pasteNode.addFather(node);
+                                        MainApp.getOntologyControler().modified(true);
+                                        MainApp.getOntologyControler().refreshTree();
+                                    }
+                                }
+                            }
+                        } else {
+                            // paste on another hierachie
+                            Alert pbHierarchy = new Alert(Alert.AlertType.ERROR);
+                            pbHierarchy.setTitle("Can't paste concept here");
+                            pbHierarchy.setHeaderText("Copy § Cut are allowed in the same hierarchy");
+                            pbHierarchy.initOwner(MainApp.primaryStage);
+                            pbHierarchy.initModality(Modality.WINDOW_MODAL);
+                            pbHierarchy.show();
+                        }
+                    }
+                }
+            }
+        });
+
         exactMatchColumn.setCellFactory(column -> {
 //            return new TableCell<ObservableObjectValue<Hyperlink>, Hyperlink>() {
             return new TableCell<SimpleStringProperty, Hyperlink>() {
-- 
GitLab