File Tree View Sample(Part3) Drag and Drop
This is the 2nd day of the JavaFX Advent calendar.JavaFX Advent Calendar 2013 - Adventar
The 1st day is 曲線のアニメーション - JavaFX in the Box by Mr.@skrb
The 3rd day is JavaFXでめくるエフェクト!! | るーつにゃんブログ by Mr.
@rootsu1024x
I added the following one function to the previous sample application.File Tree View Sample(Part 2) - tomoTakaの日記
- Copying a file by a drag-and-drop operation on TreeView.
Thanks to this articleDrag-and-Drop Feature in JavaFX Applications | JavaFX 2 Tutorials and Documentation ,it is not difficult to implement this function.
I used JavaSE8 for this sample application.
- Screen1(select the source file)
- Screen2(When the mouse pointer hovers over a target that fits the given drag-and-drop gesture, the target changes its background color)
- Screen3(The dialog shows up when the target has the item same as the sources)
- Screen4(when the mouse pointer hovers over the sources parent directory, the background color does not change.)
- code1(Starting the Drag-and-Drop Gesture on a Source)
- Define a file(isLead) as a source
- Pass the transfer mode only COPY, because MOVE event does not happen MAX OS X 10.7?(I will try this after get a new MAC)
- Put a file on a dragboard, since there is no method about Path.
cell.setOnDragDetected(event -> { TreeItem<PathItem> item = cell.getTreeItem(); if (item != null && item.isLeaf()) { Dragboard db = cell.startDragAndDrop(TransferMode.COPY); ClipboardContent content = new ClipboardContent(); List<File> files = Arrays.asList(cell.getTreeItem().getValue().getPath().toFile()); content.putFiles(files); db.setContent(content); event.consume(); } });
- code2(Handling a DRAG_OVER Event on a Target)
- Define a directory(!isLead) as a target
- Accept it only if it is not dragged from the same item nor the same parent(see Screen4)
- Allow only copying
cell.setOnDragOver(event -> { TreeItem<PathItem> item = cell.getTreeItem(); if ((item != null && !item.isLeaf()) && event.getGestureSource() != cell && event.getDragboard().hasFiles()) { Path targetPath = cell.getTreeItem().getValue().getPath(); PathTreeCell sourceCell = (PathTreeCell) event.getGestureSource(); final Path sourceParentPath = sourceCell.getTreeItem().getValue().getPath().getParent(); if (sourceParentPath.compareTo(targetPath) != 0) { event.acceptTransferModes(TransferMode.COPY); } } event.consume(); });
- code3(Providing Visual Feedback by a Gesture Target)
- Set the condition like the code2
- The target changes its backgound color here(see Screen2)
cell.setOnDragEntered(event -> { TreeItem<PathItem> item = cell.getTreeItem(); if ((item != null && !item.isLeaf()) && event.getGestureSource() != cell && event.getDragboard().hasFiles()) { Path targetPath = cell.getTreeItem().getValue().getPath(); PathTreeCell sourceCell = (PathTreeCell) event.getGestureSource(); final Path sourceParentPath = sourceCell.getTreeItem().getValue().getPath().getParent(); if (sourceParentPath.compareTo(targetPath) != 0) { cell.setStyle("-fx-background-color: powderblue;"); } } event.consume(); });
- code4(Handling a DRAG_EXIT Event on a Target)
- The target restore its original color here
cell.setOnDragExited(event -> { cell.setStyle("-fx-background-color: white"); event.consume(); });
- code5(Handling a DRAG_DROPPED Event on a Target)
- The dialog shows up when the target has the item same as the sources.(see Screen 3, code 7)
- If OK button is clicked, copying of files starts
- Add the source item to the target directory as a leaf, if the item does not exist on the target
cell.setOnDragDropped(event -> { Dragboard db = event.getDragboard(); boolean success = false; if (db.hasFiles()) { final Path source = db.getFiles().get(0).toPath(); final Path target = Paths.get( cell.getTreeItem().getValue().getPath().toAbsolutePath().toString(), source.getFileName().toString()); if (Files.exists(target, LinkOption.NOFOLLOW_LINKS)) { Platform.runLater(() -> { BooleanProperty replaceProp = new SimpleBooleanProperty(); // the dialog shows up here CopyModalDialog dialog = new CopyModalDialog(stage, replaceProp); replaceProp.addListener((ObservableValue<? extends Boolean> ov, Boolean oldValue, Boolean newValue) -> { if (newValue) { // if OK button is clicked, copying of files starts FileCopyTask task = new FileCopyTask(source, target); service.submit(task); } }); }); } else { // Copying of files starts FileCopyTask task = new FileCopyTask(source, target); service.submit(task); task.setOnSucceeded(value -> { Platform.runLater(() -> { // add the source item to the target directory as a leaf TreeItem<PathItem> item = PathTreeItem.createNode(new PathItem(target)); cell.getTreeItem().getChildren().add(item); }); }); } success = true; } event.setDropCompleted(success); event.consume(); });
- code6(FileCopyTask.java)
- This class extends the Task class for running in the background.
public class FileCopyTask extends Task<Void> { private Path source; private Path target; public FileCopyTask(Path source, Path target) { this.source = source; this.target = target; } @Override protected Void call() throws Exception { Files.copy(this.source, this.target, StandardCopyOption.REPLACE_EXISTING); return null; } }
- code7(CopyModalDialog.java)
- This code shows you how to create the dialog
- replaceProp has the true value, if you click OK button
public class CopyModalDialog { public CopyModalDialog(Stage owner, final BooleanProperty replaceProp) { final Stage dialog = new Stage(StageStyle.UTILITY); dialog.initOwner(owner); dialog.initModality(Modality.APPLICATION_MODAL); GridPane root = new GridPane(); root.setPadding(new Insets(30)); root.setHgap(5); root.setVgap(10); Label label = new Label("The item already exists in this location. Do you want to replace it?"); Button okButton = new Button("OK"); okButton.setOnAction(event -> { replaceProp.set(true); dialog.hide(); }); Button cancelButton = new Button("Cancel"); cancelButton.setOnAction(event -> { replaceProp.set(false); dialog.hide(); }); root.add(label, 0, 0, 2, 1); root.addRow(1, okButton, cancelButton); dialog.setScene(new Scene(root)); dialog.show(); } }
The whole code is heretomoTaka01/FileTreeViewSample: JavaFX File ... - GitHub
I learned JavaFX a lot from the articleJava技術最前線 - JavaFX 2ではじめる、GUI開発 第14回 非同期処理:ITpro written by Mr.@skrb
keep coding...