@@ -18,11 +18,14 @@ import { PackageRootNode } from "./packageRootNode";
18
18
import { PrimaryTypeNode } from "./PrimaryTypeNode" ;
19
19
import { ProjectNode } from "./projectNode" ;
20
20
import { WorkspaceNode } from "./workspaceNode" ;
21
+ import { addLibraryGlobs } from "../controllers/libraryController" ;
22
+ import { sendError } from "vscode-extension-telemetry-wrapper" ;
21
23
22
24
export class DragAndDropController implements TreeDragAndDropController < ExplorerNode > {
23
25
24
26
dropMimeTypes : string [ ] = [
25
27
Explorer . Mime . JavaProjectExplorer ,
28
+ Explorer . Mime . TextUriList ,
26
29
] ;
27
30
dragMimeTypes : string [ ] = [
28
31
Explorer . Mime . TextUriList ,
@@ -41,6 +44,33 @@ export class DragAndDropController implements TreeDragAndDropController<Explorer
41
44
await this . dropFromJavaProjectExplorer ( target , data . value ) ;
42
45
return ;
43
46
}
47
+
48
+ let uriList : string [ ] = [ ] ;
49
+ // an undefined value will be contained with the key 'text/uri-list', so here
50
+ // we iterate all the entries to get the uri list.
51
+ // see: https://github.com/microsoft/vscode/issues/152031
52
+ dataTransfer . forEach ( ( value : DataTransferItem , key : string ) => {
53
+ if ( key === Explorer . Mime . TextUriList && value . value ) {
54
+ uriList . push ( ...( value . value as string ) . split ( "\n" ) ) ;
55
+ }
56
+ } ) ;
57
+
58
+ uriList = uriList . map ( u => {
59
+ try {
60
+ const uri = Uri . parse ( u , true /* strict */ ) ;
61
+ if ( uri . scheme !== "file" ) {
62
+ return undefined ;
63
+ }
64
+ return u ;
65
+ } catch ( e ) {
66
+ sendError ( e ) ;
67
+ return undefined ;
68
+ }
69
+ } ) . filter ( Boolean ) as string [ ] ;
70
+
71
+ if ( uriList . length ) {
72
+ this . dropFromFileExplorer ( target , uriList ) ;
73
+ }
44
74
}
45
75
46
76
/**
@@ -82,7 +112,7 @@ export class DragAndDropController implements TreeDragAndDropController<Explorer
82
112
* @param target the drop node.
83
113
* @param uri uri in the data transfer.
84
114
*/
85
- public async dropFromJavaProjectExplorer ( target : ExplorerNode | undefined , uri : string ) : Promise < void > {
115
+ private async dropFromJavaProjectExplorer ( target : ExplorerNode | undefined , uri : string ) : Promise < void > {
86
116
const source : DataNode | undefined = explorerNodeCache . getDataNode ( Uri . parse ( uri ) ) ;
87
117
if ( ! this . isDraggableNode ( source ) ) {
88
118
return ;
@@ -98,18 +128,38 @@ export class DragAndDropController implements TreeDragAndDropController<Explorer
98
128
}
99
129
100
130
if ( target instanceof ContainerNode ) {
101
- if ( target . getContainerType ( ) !== ContainerType . ReferencedLibrary ) {
131
+ if ( target . getContainerType ( ) !== ContainerType . ReferencedLibrary
132
+ || ! ( target . getParent ( ) as ProjectNode ) . isUnmanagedFolder ( ) ) {
102
133
return ;
103
134
}
104
135
105
- if ( ! ( target . getParent ( ) as ProjectNode ) . isUnmanagedFolder ( ) ) {
136
+ this . addReferencedLibraries ( [ source ?. uri ! ] ) ;
137
+ } else if ( target instanceof PackageRootNode || target instanceof PackageNode
138
+ || target instanceof FolderNode ) {
139
+ await this . move ( source ! , target ) ;
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Handle the DnD event which comes from VS Code's file explorer or system file explorer.
145
+ * @param target the drop node.
146
+ * @param uris uris of the dragged files.
147
+ */
148
+ private async dropFromFileExplorer ( target : ExplorerNode | undefined , uris : string [ ] ) : Promise < void > {
149
+ if ( ! this . isDroppableNode ( target ) ) {
150
+ return ;
151
+ }
152
+
153
+ if ( target instanceof ContainerNode ) {
154
+ if ( target . getContainerType ( ) !== ContainerType . ReferencedLibrary
155
+ || ! ( target . getParent ( ) as ProjectNode ) . isUnmanagedFolder ( ) ) {
106
156
return ;
107
157
}
108
158
109
- // TODO: referenced library
159
+ this . addReferencedLibraries ( uris ) ;
110
160
} else if ( target instanceof PackageRootNode || target instanceof PackageNode
111
161
|| target instanceof FolderNode ) {
112
- await this . move ( source ! , target ) ;
162
+ // TODO: copy the resources to other nodes
113
163
}
114
164
}
115
165
@@ -161,7 +211,7 @@ export class DragAndDropController implements TreeDragAndDropController<Explorer
161
211
return false ;
162
212
}
163
213
164
- if ( node instanceof DataNode && ! node . uri ) {
214
+ if ( node instanceof DataNode && ! ( node instanceof ContainerNode ) && ! node . uri ) {
165
215
return false ;
166
216
}
167
217
@@ -232,4 +282,34 @@ export class DragAndDropController implements TreeDragAndDropController<Explorer
232
282
233
283
return true ;
234
284
}
285
+
286
+ /**
287
+ * Parse the input uri strings to pattern strings and set them to
288
+ * the setting: 'java.project.referencedLibraries'.
289
+ * @param uriStrings uri strings
290
+ */
291
+ private async addReferencedLibraries ( uriStrings : string [ ] ) : Promise < void > {
292
+ const pattern = ( await Promise . all ( uriStrings . map ( async uriString => {
293
+ try {
294
+ const uri = Uri . parse ( uriString , true /* strict */ ) ;
295
+ if ( uri . scheme !== "file" ) {
296
+ return undefined ;
297
+ }
298
+ const isDirectory = ( await fse . stat ( uri . fsPath ) ) . isDirectory ( ) ;
299
+ // only jars and folders can be dropped into referenced libraries.
300
+ if ( ! isDirectory && path . extname ( uri . fsPath ) !== ".jar" ) {
301
+ return undefined ;
302
+ }
303
+ const uriPath = workspace . asRelativePath ( uri , false ) ;
304
+ return isDirectory ? uriPath + "/**/*.jar" : uriPath ;
305
+ } catch ( e ) {
306
+ sendError ( e ) ;
307
+ return undefined ;
308
+ }
309
+ } ) ) ) . filter ( Boolean ) ;
310
+
311
+ if ( pattern ) {
312
+ addLibraryGlobs ( pattern as string [ ] ) ;
313
+ }
314
+ }
235
315
}
0 commit comments