Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable resourceurls #140709

Merged
merged 6 commits into from
Jan 25, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions src/vs/editor/browser/services/openerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { URI } from 'vs/base/common/uri';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { EditorOpenContext } from 'vs/platform/editor/common/editor';
import { IExternalOpener, IExternalUriResolver, IOpener, IOpenerService, IResolvedExternalUri, IValidator, matchesScheme, matchesSomeScheme, OpenOptions, ResolveExternalUriOptions } from 'vs/platform/opener/common/opener';
import { IExternalOpener, IExternalUriResolver, IOpener, IOpenerService, IResolvedExternalUri, IValidator, matchesScheme, matchesSomeScheme, OpenOptions, ResolveExternalUriOptions, selectionFragment } from 'vs/platform/opener/common/opener';

class CommandOpener implements IOpener {

Expand Down Expand Up @@ -62,16 +62,8 @@ class EditorOpener implements IOpener {
if (typeof target === 'string') {
target = URI.parse(target);
}
let selection: { startLineNumber: number; startColumn: number; } | undefined = undefined;
const match = /^L?(\d+)(?:,(\d+))?/.exec(target.fragment);
if (match) {
// support file:///some/file.js#73,84
// support file:///some/file.js#L73
selection = {
startLineNumber: parseInt(match[1]),
startColumn: match[2] ? parseInt(match[2]) : 1
};
// remove fragment
const selection: { startLineNumber: number; startColumn: number; } | undefined = selectionFragment(target);
if (selection) {
target = target.with({ fragment: '' });
}

Expand Down
14 changes: 14 additions & 0 deletions src/vs/platform/opener/common/opener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,17 @@ export function matchesScheme(target: URI | string, scheme: string): boolean {
export function matchesSomeScheme(target: URI | string, ...schemes: string[]): boolean {
return schemes.some(scheme => matchesScheme(target, scheme));
}

export function selectionFragment(target: URI): { startLineNumber: number; startColumn: number; } | undefined {
let selection: { startLineNumber: number; startColumn: number; } | undefined = undefined;
const match = /^L?(\d+)(?:,(\d+))?/.exec(target.fragment);
if (match) {
// support file:///some/file.js#73,84
// support file:///some/file.js#L73
selection = {
startLineNumber: parseInt(match[1]),
startColumn: match[2] ? parseInt(match[2]) : 1
};
}
return selection;
}
39 changes: 37 additions & 2 deletions src/vs/workbench/browser/dnd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import { parse, stringify } from 'vs/base/common/marshalling';
import { ILabelService } from 'vs/platform/label/common/label';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { withNullAsUndefined } from 'vs/base/common/types';
import { ITreeDataTransfer } from 'vs/workbench/common/views';
import { selectionFragment } from 'vs/platform/opener/common/opener';

//#region Editor / Resources DND

Expand All @@ -46,6 +48,11 @@ export class DraggedEditorGroupIdentifier {
constructor(readonly identifier: GroupIdentifier) { }
}

export class DraggedExtensionTreeItemsIdentifier {
bpasero marked this conversation as resolved.
Show resolved Hide resolved

constructor(readonly identifier: string) { }
}

export const CodeDataTransfers = {
EDITORS: 'CodeEditors',
FILES: 'CodeFiles'
Expand Down Expand Up @@ -130,6 +137,34 @@ export function extractEditorsDropData(e: DragEvent): Array<IDraggedResourceEdit
return editors;
}

export async function extractTreeDropData(dataTransfer: ITreeDataTransfer): Promise<Array<IDraggedResourceEditorInput>> {
alexr00 marked this conversation as resolved.
Show resolved Hide resolved
const editors: IDraggedResourceEditorInput[] = [];
const resourcesKey = DataTransfers.RESOURCES.toLowerCase();
// Data Transfer: Resources
if (dataTransfer.has(resourcesKey)) {
try {
const rawResourcesData = await dataTransfer.get(resourcesKey)?.asString();
if (rawResourcesData) {
const rawResourceList = JSON.parse(rawResourcesData);
for (const resourceRaw of rawResourceList) {
if (resourceRaw.indexOf(':') > 0) { // mitigate https://github.com/microsoft/vscode/issues/124946
alexr00 marked this conversation as resolved.
Show resolved Hide resolved
const resource = URI.parse(resourceRaw);
editors.push({
resource,
options: {
selection: selectionFragment(resource)
}
});
}
}
}
} catch (error) {
// Invalid transfer
}
}
return editors;
}

export interface IFileDropData {
name: string;
data: VSBuffer;
Expand Down Expand Up @@ -195,8 +230,8 @@ export class ResourcesDropHandler {
) {
}

async handleDrop(event: DragEvent, resolveTargetGroup: () => IEditorGroup | undefined, afterDrop: (targetGroup: IEditorGroup | undefined) => void, targetIndex?: number): Promise<void> {
const editors = extractEditorsDropData(event);
async handleDrop(event: DragEvent | ITreeDataTransfer, resolveTargetGroup: () => IEditorGroup | undefined, afterDrop: (targetGroup: IEditorGroup | undefined) => void, targetIndex?: number): Promise<void> {
const editors = event instanceof DragEvent ? extractEditorsDropData(event) : await extractTreeDropData(event);
if (!editors.length) {
return;
}
Expand Down
26 changes: 24 additions & 2 deletions src/vs/workbench/browser/parts/editor/editorDropTarget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import 'vs/css!./media/editordroptarget';
import { LocalSelectionTransfer, DraggedEditorIdentifier, ResourcesDropHandler, DraggedEditorGroupIdentifier, DragAndDropObserver, containsDragType, CodeDataTransfers, extractFilesDropData } from 'vs/workbench/browser/dnd';
import { LocalSelectionTransfer, DraggedEditorIdentifier, ResourcesDropHandler, DraggedEditorGroupIdentifier, DragAndDropObserver, containsDragType, CodeDataTransfers, extractFilesDropData, DraggedExtensionTreeItemsIdentifier } from 'vs/workbench/browser/dnd';
import { addDisposableListener, EventType, EventHelper, isAncestor } from 'vs/base/browser/dom';
import { IEditorGroupsAccessor, IEditorGroupView, fillActiveEditorViewState } from 'vs/workbench/browser/parts/editor/editor';
import { EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
Expand All @@ -21,6 +21,8 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { assertIsDefined, assertAllDefined } from 'vs/base/common/types';
import { Schemas } from 'vs/base/common/network';
import { URI } from 'vs/base/common/uri';
import { ITreeViewsDragAndDropService } from 'vs/workbench/services/views/common/treeViewsDragAndDropService';
import { ITreeDataTransfer } from 'vs/workbench/common/views';

interface IDropOperation {
splitDirection?: GroupDirection;
Expand All @@ -40,14 +42,16 @@ class DropOverlay extends Themable {

private readonly editorTransfer = LocalSelectionTransfer.getInstance<DraggedEditorIdentifier>();
private readonly groupTransfer = LocalSelectionTransfer.getInstance<DraggedEditorGroupIdentifier>();
private readonly treeItemsTransfer = LocalSelectionTransfer.getInstance<DraggedExtensionTreeItemsIdentifier>();

constructor(
private accessor: IEditorGroupsAccessor,
private groupView: IEditorGroupView,
@IThemeService themeService: IThemeService,
@IInstantiationService private instantiationService: IInstantiationService,
@IEditorService private readonly editorService: IEditorService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@ITreeViewsDragAndDropService private readonly treeViewsDragAndDropService: ITreeViewsDragAndDropService<ITreeDataTransfer>
) {
super(themeService);

Expand Down Expand Up @@ -292,6 +296,24 @@ class DropOverlay extends Themable {
}
}

// Check for tree items
else if (this.treeItemsTransfer.hasData(DraggedExtensionTreeItemsIdentifier.prototype)) {
const data = this.treeItemsTransfer.getData(DraggedExtensionTreeItemsIdentifier.prototype);
if (Array.isArray(data)) {
const treeData = Promise.all(
data.map(id => this.treeViewsDragAndDropService.removeDragOperationTransfer(id.identifier)));
treeData.then(dataTransferItems => {
const dropHandler = this.instantiationService.createInstance(ResourcesDropHandler, { allowWorkspaceOpen: true /* open workspace instead of file if dropped */ });
dataTransferItems.forEach(dataTransferItem => {
alexr00 marked this conversation as resolved.
Show resolved Hide resolved
if (dataTransferItem) {
dropHandler.handleDrop(dataTransferItem, () => ensureTargetGroup(), targetGroup => targetGroup?.focus());
}
});
});
}
this.treeItemsTransfer.clearData(DraggedExtensionTreeItemsIdentifier.prototype);
}

// Web: check for file transfer
else if (isWeb && containsDragType(event, DataTransfers.FILES)) {
let targetGroup: IEditorGroupView | undefined = undefined;
Expand Down
5 changes: 4 additions & 1 deletion src/vs/workbench/browser/parts/views/treeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cance
import { Command } from 'vs/editor/common/languages';
import { isCancellationError } from 'vs/base/common/errors';
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
import { CodeDataTransfers, fillEditorsDragData } from 'vs/workbench/browser/dnd';
import { CodeDataTransfers, DraggedExtensionTreeItemsIdentifier, fillEditorsDragData, LocalSelectionTransfer } from 'vs/workbench/browser/dnd';
import { Schemas } from 'vs/base/common/network';
import { ITreeViewsDragAndDropService } from 'vs/workbench/services/views/common/treeViewsDragAndDropService';
import { generateUuid } from 'vs/base/common/uuid';
Expand Down Expand Up @@ -1241,6 +1241,8 @@ const TREE_DRAG_UUID_MIME = 'tree-dnd';

export class CustomTreeViewDragAndDrop implements ITreeDragAndDrop<ITreeItem> {
private readonly treeMimeType: string;
private readonly treeItemsTransfer = LocalSelectionTransfer.getInstance<DraggedExtensionTreeItemsIdentifier>();

constructor(
private readonly treeId: string,
@ILabelService private readonly labelService: ILabelService,
Expand All @@ -1262,6 +1264,7 @@ export class CustomTreeViewDragAndDrop implements ITreeDragAndDrop<ITreeItem> {
const uuid = generateUuid();
this.treeViewsDragAndDropService.addDragOperationTransfer(uuid, this.dndController.handleDrag(itemHandles, uuid));
originalEvent.dataTransfer.setData(TREE_DRAG_UUID_MIME, uuid);
this.treeItemsTransfer.setData([new DraggedExtensionTreeItemsIdentifier(uuid)], DraggedExtensionTreeItemsIdentifier.prototype);
}

private addResourceInfoToTransfer(originalEvent: DragEvent, resources: URI[]) {
Expand Down
4 changes: 4 additions & 0 deletions src/vscode-dts/vscode.proposed.treeViewDragAndDrop.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ declare module 'vscode' {
* When the items are dropped on **another tree item** in **the same tree**, your `TreeDataTransferItem` objects
* will be preserved. See the documentation for `TreeDataTransferItem` for how best to take advantage of this.
*
* To add a data transfer item that can be dragged into the editor, use the application specific mime type "resourceurls".
* The data for "resourceurls" should be an array of `toString()`ed Uris. To specify a cursor position in the file,
* set the Uri's fragment to `L3,5`, where 3 is the line number and 5 is the column number.
*
* @param source The source items for the drag and drop operation.
* @param treeDataTransfer The data transfer associated with this drag.
*/
Expand Down