Skip to content

Commit 9eaa4ed

Browse files
committed
Support drag-n-drop to root in Filebrowser app
1 parent c04ec8b commit 9eaa4ed

File tree

1 file changed

+72
-28
lines changed

1 file changed

+72
-28
lines changed

app/filebrowser/src/main/java/org/phoebus/applications/filebrowser/FileTreeCell.java

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,5 @@
11
package org.phoebus.applications.filebrowser;
22

3-
import static org.phoebus.applications.filebrowser.FileBrowser.logger;
4-
5-
import java.io.File;
6-
import java.net.URI;
7-
import java.net.URL;
8-
import java.text.MessageFormat;
9-
import java.util.ArrayList;
10-
import java.util.List;
11-
import java.util.logging.Level;
12-
import java.util.stream.Collectors;
13-
14-
import org.phoebus.framework.jobs.JobManager;
15-
import org.phoebus.framework.spi.AppDescriptor;
16-
import org.phoebus.framework.util.ResourceParser;
17-
import org.phoebus.framework.workbench.FileHelper;
18-
import org.phoebus.ui.application.ApplicationLauncherService;
19-
import org.phoebus.ui.dialog.ExceptionDetailsErrorDialog;
20-
import org.phoebus.ui.javafx.ImageCache;
21-
import org.phoebus.ui.javafx.PlatformInfo;
22-
233
import javafx.application.Platform;
244
import javafx.collections.ObservableList;
255
import javafx.scene.control.TreeItem;
@@ -36,16 +16,39 @@
3616
import javafx.scene.layout.BorderStrokeStyle;
3717
import javafx.scene.layout.CornerRadii;
3818
import javafx.scene.paint.Color;
19+
import org.phoebus.framework.jobs.JobManager;
20+
import org.phoebus.framework.spi.AppDescriptor;
21+
import org.phoebus.framework.util.ResourceParser;
22+
import org.phoebus.framework.workbench.FileHelper;
23+
import org.phoebus.ui.application.ApplicationLauncherService;
24+
import org.phoebus.ui.dialog.ExceptionDetailsErrorDialog;
25+
import org.phoebus.ui.javafx.ImageCache;
26+
import org.phoebus.ui.javafx.PlatformInfo;
27+
28+
import java.io.File;
29+
import java.net.URI;
30+
import java.net.URL;
31+
import java.text.MessageFormat;
32+
import java.util.ArrayList;
33+
import java.util.List;
34+
import java.util.logging.Level;
35+
import java.util.stream.Collectors;
36+
37+
import static org.phoebus.applications.filebrowser.FileBrowser.logger;
3938

4039
@SuppressWarnings("nls")
4140
final class FileTreeCell extends TreeTableCell<FileInfo, File> {
4241
static final Image file_icon = ImageCache.getImage(ImageCache.class, "/icons/file_obj.png");
4342
static final Image folder_icon = ImageCache.getImage(ImageCache.class, "/icons/fldr_obj.png");
44-
static final Image newDisplayIcon = ImageCache.getImage(ImageCache.class, "/icons/display.png");
4543

4644
private static final Border BORDER = new Border(new BorderStroke(Color.GREEN, BorderStrokeStyle.SOLID,
4745
new CornerRadii(5.0), BorderStroke.THIN));
4846

47+
/**
48+
* Used to determine if the user has dropped a selection onto the area below the tree view
49+
*/
50+
private boolean dropOnRoot;
51+
4952
public FileTreeCell()
5053
{
5154
enableDragDrop();
@@ -84,15 +87,14 @@ private void enableDragDrop()
8487
setOnDragDone(event ->
8588
{
8689
final File file = getItem();
87-
8890
if (event.getTransferMode() == TransferMode.MOVE &&
8991
file != null)
9092
{
9193
logger.log(Level.FINE, "Drag (MOVE) completed. Deleting moved " + file);
9294
// Might want to check if file.exists() in case move failed,
9395
// but actual move is performed in background, so right now file
9496
// might still be present...
95-
final TreeItem<FileInfo> deleted_item = getTreeTableRow().getTreeItem();
97+
final TreeItem<FileInfo> deleted_item = getTableRow().getTreeItem();
9698
deleted_item.getParent().getChildren().remove(deleted_item);
9799
}
98100
else
@@ -106,10 +108,17 @@ private void enableDragDrop()
106108
setOnDragOver(event ->
107109
{
108110
final File file = getItem();
109-
if (file != null && event.getDragboard().hasFiles() && !event.getDragboard().getFiles().contains(file))
111+
// If user drags to the "empty" area below the tree view, file is null.
112+
// This suggests the intention to move/copy items to the root of the view.
113+
dropOnRoot = file == null;
114+
if (event.getDragboard().hasFiles() && !event.getDragboard().getFiles().contains(file))
110115
{
111116
event.acceptTransferModes(event.getTransferMode());
112-
setBorder(BORDER);
117+
// Do not set border on TreeView items that "exist" in the TreeView model, but are invisible.
118+
// Because it looks weird rendering a border around an empty space...
119+
if(!dropOnRoot){
120+
setBorder(BORDER);
121+
}
113122
}
114123
event.consume();
115124
});
@@ -123,7 +132,19 @@ private void enableDragDrop()
123132
// A file has been dropped into this dir, or this file's directory
124133
setOnDragDropped(event ->
125134
{
126-
TreeItem<FileInfo> target_item = getTreeTableRow().getTreeItem();
135+
TreeItem<FileInfo> target_item;
136+
if(dropOnRoot){
137+
// User dropped on area below the tree view
138+
target_item = getTreeTableView().getRoot();
139+
// If selection is contained in the root target, abort.
140+
if(isSelectionInTarget(target_item, event.getDragboard())){
141+
event.consume();
142+
return;
143+
}
144+
}
145+
else{
146+
target_item = getTableRow().getTreeItem();
147+
}
127148

128149
if (target_item.getValue() != null && !target_item.getValue().file.isDirectory())
129150
target_item = target_item.getParent();
@@ -187,11 +208,11 @@ private void move_or_copy(final File file, final TreeItem<FileInfo> target_item,
187208
protected void updateItem(final File file, final boolean empty) {
188209
super.updateItem(file, empty);
189210

190-
if (empty || file == null || getTreeTableRow() == null || getTreeTableRow().getTreeItem() == null) {
211+
if (empty || file == null || getTableRow() == null || getTableRow().getTreeItem() == null) {
191212
setText(null);
192213
setGraphic(null);
193214
} else {
194-
if (getTreeTableRow().getTreeItem().getParent() == null) {
215+
if (getTableRow().getTreeItem().getParent() == null) {
195216
// Root (actually hidden, so this is never called)
196217
setText(file.getAbsolutePath());
197218
} else {
@@ -237,4 +258,27 @@ else if(event.isAltDown() && PlatformInfo.is_mac_os_x){
237258
}
238259
return TransferMode.MOVE;
239260
}
261+
262+
/**
263+
* Checks if the dragboard files - if any - are present in the target.
264+
* @param target {@link TreeItem} representing the target file onto which user has dropped a selection.
265+
* @param dragboard The {@link Dragboard} containing a selection, if any.
266+
* @return <code>true</code> if any of the {@link Dragboard} files is found in the target.
267+
*/
268+
private boolean isSelectionInTarget(TreeItem<FileInfo> target, Dragboard dragboard){
269+
if(!dragboard.hasFiles()){
270+
return false;
271+
}
272+
List<File> filesInRoot =
273+
target.getChildren().stream().map(item -> item.getValue().file.getAbsoluteFile()).collect(Collectors.toList());
274+
for(File fileSelection : dragboard.getFiles()){
275+
for(File fileInRoot : filesInRoot){
276+
if(fileInRoot.getAbsoluteFile().equals(fileSelection.getAbsoluteFile())){
277+
return true;
278+
}
279+
}
280+
}
281+
282+
return false;
283+
}
240284
}

0 commit comments

Comments
 (0)