Skip to content

Commit f837742

Browse files
authored
Root folders drag and drop (microsoft#204153)
1 parent 981343c commit f837742

File tree

1 file changed

+60
-15
lines changed

1 file changed

+60
-15
lines changed

src/vs/workbench/contrib/files/browser/views/explorerViewer.ts

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
11031103
const iconLabelName = getIconLabelNameFromHTMLElement(originalEvent.target);
11041104

11051105
if (iconLabelName && iconLabelName.index < iconLabelName.count - 1) {
1106-
const result = this.handleDragOver(data, compressedTarget, targetIndex, originalEvent);
1106+
const result = this.handleDragOver(data, compressedTarget, targetIndex, targetSector, originalEvent);
11071107

11081108
if (result) {
11091109
if (iconLabelName.element !== this.compressedDragOverElement) {
@@ -1127,10 +1127,10 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
11271127
}
11281128

11291129
this.compressedDropTargetDisposable.dispose();
1130-
return this.handleDragOver(data, target, targetIndex, originalEvent);
1130+
return this.handleDragOver(data, target, targetIndex, targetSector, originalEvent);
11311131
}
11321132

1133-
private handleDragOver(data: IDragAndDropData, target: ExplorerItem | undefined, targetIndex: number | undefined, originalEvent: DragEvent): boolean | ITreeDragOverReaction {
1133+
private handleDragOver(data: IDragAndDropData, target: ExplorerItem | undefined, targetIndex: number | undefined, targetSector: ListViewTargetSector | undefined, originalEvent: DragEvent): boolean | ITreeDragOverReaction {
11341134
const isCopy = originalEvent && ((originalEvent.ctrlKey && !isMacintosh) || (originalEvent.altKey && isMacintosh));
11351135
const isNative = data instanceof NativeDragAndDropData;
11361136
const effectType = (isNative || isCopy) ? ListDragOverEffectType.Copy : ListDragOverEffectType.Move;
@@ -1151,6 +1151,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
11511151
// In-Explorer DND
11521152
else {
11531153
const items = FileDragAndDrop.getStatsFromDragAndDropData(data as ElementsDragAndDropData<ExplorerItem, ExplorerItem[]>);
1154+
const isRootsReorder = items.every(item => item.isRoot);
11541155

11551156
if (!target) {
11561157
// Dropping onto the empty area. Do not accept if items dragged are already
@@ -1159,6 +1160,11 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
11591160
return false;
11601161
}
11611162

1163+
// root is added after last root folder when hovering on empty background
1164+
if (isRootsReorder) {
1165+
return { accept: true, effect: { type: ListDragOverEffectType.Move, position: ListDragOverEffectPosition.After } };
1166+
}
1167+
11621168
return { accept: true, bubble: TreeDragOverBubble.Down, effect, autoExpand: false };
11631169
}
11641170

@@ -1171,17 +1177,12 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
11711177
}
11721178

11731179
if (items.some((source) => {
1174-
if (source.isRoot && target instanceof ExplorerItem && !target.isRoot) {
1175-
return true; // Root folder can not be moved to a non root file stat.
1180+
if (source.isRoot) {
1181+
return false; // Root folders are handled seperately
11761182
}
11771183

11781184
if (this.uriIdentityService.extUri.isEqual(source.resource, target.resource)) {
1179-
return true; // Can not move anything onto itself
1180-
}
1181-
1182-
if (source.isRoot && target instanceof ExplorerItem && target.isRoot) {
1183-
// Disable moving workspace roots in one another
1184-
return false;
1185+
return true; // Can not move anything onto itself excpet for root folders
11851186
}
11861187

11871188
if (!isCopy && this.uriIdentityService.extUri.isEqual(dirname(source.resource), target.resource)) {
@@ -1196,6 +1197,24 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
11961197
})) {
11971198
return false;
11981199
}
1200+
1201+
// reordering roots
1202+
if (isRootsReorder) {
1203+
if (!target.isRoot) {
1204+
return false;
1205+
}
1206+
1207+
let dropEffectPosition: ListDragOverEffectPosition | undefined = undefined;
1208+
switch (targetSector) {
1209+
case ListViewTargetSector.TOP:
1210+
case ListViewTargetSector.CENTER_TOP:
1211+
dropEffectPosition = ListDragOverEffectPosition.Before; break;
1212+
case ListViewTargetSector.CENTER_BOTTOM:
1213+
case ListViewTargetSector.BOTTOM:
1214+
dropEffectPosition = ListDragOverEffectPosition.After; break;
1215+
}
1216+
return { accept: true, effect: { type: ListDragOverEffectType.Move, position: dropEffectPosition } };
1217+
}
11991218
}
12001219

12011220
// All (target = model)
@@ -1268,6 +1287,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
12681287
// Find parent to add to
12691288
if (!target) {
12701289
target = this.explorerService.roots[this.explorerService.roots.length - 1];
1290+
targetSector = ListViewTargetSector.BOTTOM;
12711291
}
12721292
if (!target.isDirectory && target.parent) {
12731293
target = target.parent;
@@ -1298,14 +1318,14 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
12981318

12991319
// In-Explorer DND (Move/Copy file)
13001320
else {
1301-
await this.handleExplorerDrop(data as ElementsDragAndDropData<ExplorerItem, ExplorerItem[]>, resolvedTarget, originalEvent);
1321+
await this.handleExplorerDrop(data as ElementsDragAndDropData<ExplorerItem, ExplorerItem[]>, resolvedTarget, targetIndex, targetSector, originalEvent);
13021322
}
13031323
} catch (error) {
13041324
this.dialogService.error(toErrorMessage(error));
13051325
}
13061326
}
13071327

1308-
private async handleExplorerDrop(data: ElementsDragAndDropData<ExplorerItem, ExplorerItem[]>, target: ExplorerItem, originalEvent: DragEvent): Promise<void> {
1328+
private async handleExplorerDrop(data: ElementsDragAndDropData<ExplorerItem, ExplorerItem[]>, target: ExplorerItem, targetIndex: number | undefined, targetSector: ListViewTargetSector | undefined, originalEvent: DragEvent): Promise<void> {
13091329
const elementsData = FileDragAndDrop.getStatsFromDragAndDropData(data);
13101330
const distinctItems = new Map(elementsData.map(element => [element, this.isCollapsed(element)]));
13111331

@@ -1353,7 +1373,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
13531373
}
13541374
}
13551375

1356-
await this.doHandleRootDrop(items.filter(s => s.isRoot), target);
1376+
await this.doHandleRootDrop(items.filter(s => s.isRoot), target, targetSector);
13571377

13581378
const sources = items.filter(s => !s.isRoot);
13591379
if (isCopy) {
@@ -1363,13 +1383,14 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
13631383
return this.doHandleExplorerDropOnMove(sources, target);
13641384
}
13651385

1366-
private async doHandleRootDrop(roots: ExplorerItem[], target: ExplorerItem): Promise<void> {
1386+
private async doHandleRootDrop(roots: ExplorerItem[], target: ExplorerItem, targetSector: ListViewTargetSector | undefined): Promise<void> {
13671387
if (roots.length === 0) {
13681388
return;
13691389
}
13701390

13711391
const folders = this.contextService.getWorkspace().folders;
13721392
let targetIndex: number | undefined;
1393+
const sourceIndices: number[] = [];
13731394
const workspaceCreationData: IWorkspaceFolderCreationData[] = [];
13741395
const rootsToMove: IWorkspaceFolderCreationData[] = [];
13751396

@@ -1378,10 +1399,20 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
13781399
uri: folders[index].uri,
13791400
name: folders[index].name
13801401
};
1402+
1403+
// Is current target
13811404
if (target instanceof ExplorerItem && this.uriIdentityService.extUri.isEqual(folders[index].uri, target.resource)) {
13821405
targetIndex = index;
13831406
}
13841407

1408+
// Is current source
1409+
for (const root of roots) {
1410+
if (this.uriIdentityService.extUri.isEqual(folders[index].uri, root.resource)) {
1411+
sourceIndices.push(index);
1412+
break;
1413+
}
1414+
}
1415+
13851416
if (roots.every(r => r.resource.toString() !== folders[index].uri.toString())) {
13861417
workspaceCreationData.push(data);
13871418
} else {
@@ -1390,6 +1421,20 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
13901421
}
13911422
if (targetIndex === undefined) {
13921423
targetIndex = workspaceCreationData.length;
1424+
} else {
1425+
switch (targetSector) {
1426+
case ListViewTargetSector.BOTTOM:
1427+
case ListViewTargetSector.CENTER_BOTTOM:
1428+
targetIndex++;
1429+
break;
1430+
}
1431+
// Adjust target index if source was located before target.
1432+
// The move will cause the index to change
1433+
for (const sourceIndex of sourceIndices) {
1434+
if (sourceIndex < targetIndex) {
1435+
targetIndex--;
1436+
}
1437+
}
13931438
}
13941439

13951440
workspaceCreationData.splice(targetIndex, 0, ...rootsToMove);

0 commit comments

Comments
 (0)