11package 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-
233import javafx .application .Platform ;
244import javafx .collections .ObservableList ;
255import javafx .scene .control .TreeItem ;
3616import javafx .scene .layout .BorderStrokeStyle ;
3717import javafx .scene .layout .CornerRadii ;
3818import 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" )
4140final 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