package org.jftclient.tree; import java.io.File; import org.jftclient.JFTText; import org.jftclient.OutputPanel; import org.jftclient.ssh.Connection; import javafx.event.ActionEvent; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; import javafx.scene.control.TextField; import javafx.scene.control.TreeCell; import javafx.scene.control.TreeItem; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCodeCombination; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.text.Text; import javafx.stage.Modality; import javafx.stage.Stage; public class NodeTreeCell extends TreeCell<Node> { private static final Image FOLDER_COLLAPSE_IMAGE = new Image(ClassLoader.getSystemResourceAsStream("folder.png")); private static final Image FOLDER_EXPAND_IMAGE = new Image(ClassLoader.getSystemResourceAsStream("folder-open.png")); private static final Image FILE_IMAGE = new Image(ClassLoader.getSystemResourceAsStream("file.png")); private ContextMenu contextFileMenu = new ContextMenu(); private ContextMenu contextFolderMenu = new ContextMenu(); private Connection connection; private OutputPanel outputPanel; private Image currentImage; private Tree tree; private CommonTree commonTree; public NodeTreeCell(Stage primaryStage, Connection connection, Tree tree, CommonTree commonTree) { this.connection = connection; this.outputPanel = OutputPanel.getInstance(); this.tree = tree; this.commonTree = commonTree; MenuItem refreshMenuFile = new MenuItem("Refresh"); refreshMenuFile.setOnAction((ActionEvent event) -> refreshItem()); refreshMenuFile.setAccelerator(new KeyCodeCombination(KeyCode.F5)); MenuItem refreshMenuFolder = new MenuItem("Refresh"); refreshMenuFolder.setOnAction((ActionEvent event) -> refreshItem()); refreshMenuFolder.setAccelerator(new KeyCodeCombination(KeyCode.F5)); MenuItem deleteMenuFile = new MenuItem("Delete"); deleteMenuFile.setOnAction((ActionEvent event) -> deleteItems()); deleteMenuFile.setAccelerator(new KeyCodeCombination(KeyCode.DELETE)); MenuItem deleteMenuFolder = new MenuItem("Delete"); deleteMenuFolder.setOnAction((ActionEvent event) -> deleteItems()); deleteMenuFolder.setAccelerator(new KeyCodeCombination(KeyCode.DELETE)); MenuItem newFolderMenu = new MenuItem("New Folder"); newFolderMenu.setOnAction((ActionEvent event) -> createNewFolderDialog(primaryStage)); MenuItem renameMenuFile = new MenuItem("Rename"); renameMenuFile.setOnAction((ActionEvent event) -> createRenameDialog(primaryStage)); MenuItem renameMenuFolder = new MenuItem("Rename"); renameMenuFolder.setOnAction((ActionEvent event) -> createRenameDialog(primaryStage)); contextFolderMenu.getItems().addAll(newFolderMenu, refreshMenuFolder, deleteMenuFolder, renameMenuFolder); contextFileMenu.getItems().addAll(refreshMenuFile, deleteMenuFile, renameMenuFile); } private void createRenameDialog(Stage primaryStage) { Stage dialog = new Stage(); dialog.initModality(Modality.WINDOW_MODAL); dialog.initOwner(primaryStage); VBox vbox = new VBox(); vbox.setPadding(new Insets(10d)); vbox.setSpacing(8d); Button btnOk = new Button("OK"); Button btnCancel = new Button("Cancel"); HBox hbox = new HBox(); hbox.setPadding(new Insets(10d, 10d, 10d, 10d)); hbox.setSpacing(10d); hbox.setAlignment(Pos.CENTER); btnOk.setPrefWidth(80d); btnCancel.setPrefWidth(80d); hbox.getChildren().addAll(btnOk, btnCancel); TextField itemField = new TextField(getTreeItem().getValue().getName()); vbox.getChildren().addAll(new Text("Please enter a new name:"), itemField, hbox); Scene myDialogScene = new Scene(vbox); dialog.setScene(myDialogScene); dialog.setHeight(150d); dialog.setWidth(300d); dialog.setTitle("Rename"); double x = primaryStage.getX() + primaryStage.getWidth() / 2. - dialog.getWidth() / 2.; double y = primaryStage.getY() + primaryStage.getHeight() / 2. - dialog.getHeight() / 2.; dialog.setX(x); dialog.setY(y); itemField.setOnKeyPressed(event -> { if (event.getCode() == KeyCode.ENTER) { renameItem(itemField.getText().trim(), dialog); } }); btnOk.setOnAction(event1 -> { renameItem(itemField.getText().trim(), dialog); }); btnCancel.setOnAction(event1 -> dialog.close()); dialog.showAndWait(); } private void createNewFolderDialog(Stage primaryStage) { Stage dialog = new Stage(); dialog.initModality(Modality.WINDOW_MODAL); dialog.initOwner(primaryStage); VBox vbox = new VBox(); vbox.setPadding(new Insets(10d)); vbox.setSpacing(8d); Button btnOk = new Button("OK"); Button btnCancel = new Button("Cancel"); HBox hbox = new HBox(); hbox.setPadding(new Insets(10d, 10d, 10d, 10d)); hbox.setSpacing(10d); hbox.setAlignment(Pos.CENTER); btnOk.setPrefWidth(80d); btnCancel.setPrefWidth(80d); hbox.getChildren().addAll(btnOk, btnCancel); TextField folderField = new TextField(); vbox.getChildren().addAll(new Text("Please enter name:"), folderField, hbox); Scene myDialogScene = new Scene(vbox); dialog.setScene(myDialogScene); dialog.setHeight(150d); dialog.setWidth(300d); dialog.setTitle("New Folder"); double x = primaryStage.getX() + primaryStage.getWidth() / 2. - dialog.getWidth() / 2.; double y = primaryStage.getY() + primaryStage.getHeight() / 2. - dialog.getHeight() / 2.; dialog.setX(x); dialog.setY(y); folderField.setOnKeyPressed(event -> { if (event.getCode() == KeyCode.ENTER) { createFolder(folderField, dialog); } }); btnOk.setOnAction(event1 -> { createFolder(folderField, dialog); }); btnCancel.setOnAction(event1 -> dialog.close()); dialog.showAndWait(); } private void renameItem(String newName, Stage dialog) { if (newName.isEmpty()) { dialog.close(); return; } getTreeView().getSelectionModel().clearSelection(); TreeItem<Node> parent = getTreeItem().getParent(); File newFile = new File(getTreeItem().getParent().getValue().getPath(), newName); File oldFile = new File(getItem().getPath()); if (isLocalTree()) { if (!oldFile.renameTo(newFile)) { outputPanel.println(JFTText.getLocalHost(), JFTText.textBlack("failed rename " + oldFile.getAbsolutePath() + " to " + newFile.getAbsolutePath()), JFTText.failed()); dialog.close(); return; } } else { connection.mv(oldFile.getAbsolutePath(), newFile.getAbsolutePath()); } Node node = getItem(); node.setName(newName); super.startEdit(); super.commitEdit(node); dialog.close(); parent.getChildren().setAll(tree.buildChildren(parent)); } private void createFolder(TextField folderField, Stage dialog) { String folderName = folderField.getText().trim(); if (folderName.isEmpty()) { dialog.close(); return; } File folder = new File(getItem().getPath(), folderName); String folderPath = folder.getAbsolutePath(); getTreeView().getSelectionModel().clearSelection(); if (tree.isLocal()) { if (folder.mkdirs()) { outputPanel.println(JFTText.getLocalHost(), JFTText.textBlack("mkdir -p " + folderPath)); getTreeItem().getChildren().setAll(tree.buildChildren(getTreeItem())); } else { outputPanel.println(JFTText.getLocalHost(), JFTText.textBlack("mkdir -p " + folderPath + " "), JFTText.failed()); } } else { connection.mkdir(folderPath); getTreeItem().getChildren().setAll(tree.buildChildren(getTreeItem())); } getTreeView().getSelectionModel().select(getTreeItem()); dialog.close(); } private void deleteItems() { commonTree.deleteSelectedItems(getTreeView(), tree); } @Override protected void updateItem(Node item, boolean empty) { super.updateItem(item, empty); if (!empty && item != null) { if (getTreeItem().getValue().isFile()) { setContextMenu(contextFileMenu); } else { setContextMenu(contextFolderMenu); } setText(item.getName()); if (item.isFile()) { currentImage = FILE_IMAGE; } else { if (getTreeItem().isExpanded()) { currentImage = FOLDER_EXPAND_IMAGE; } else { currentImage = FOLDER_COLLAPSE_IMAGE; } } setGraphic(new ImageView(currentImage)); if (item.getLinkDest() != null) { setTextFill(Color.BLUE); } else { setTextFill(Color.BLACK); } } else { setText(null); setGraphic(null); } } public boolean isLocalTree() { return tree.isLocal(); } public void refreshTree() { getTreeView().getSelectionModel().clearSelection(); TreeItem<Node> root = getTreeView().getRoot(); root.getChildren().setAll(tree.buildChildren(root)); } private void refreshItem() { commonTree.refresh(getTreeView(), tree); } public Image getCurrentImage() { return currentImage; } }