Skip to content

Commit

Permalink
Add keybinding for custom tree hovers
Browse files Browse the repository at this point in the history
Fixes #141021
  • Loading branch information
alexr00 committed Feb 21, 2022
1 parent ef41956 commit 25b2357
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 20 deletions.
55 changes: 52 additions & 3 deletions src/vs/workbench/api/browser/viewsExtensionPoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import { localize } from 'vs/nls';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { Registry } from 'vs/platform/registry/common/platform';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { Extensions as ViewletExtensions, PaneCompositeRegistry } from 'vs/workbench/browser/panecomposite';
import { CustomTreeView, TreeViewPane } from 'vs/workbench/browser/parts/views/treeView';
import { CustomTreeView, RawCustomTreeViewContextKey, TreeViewPane } from 'vs/workbench/browser/parts/views/treeView';
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { Extensions as ViewContainerExtensions, ICustomTreeViewDescriptor, ICustomViewDescriptor, IViewContainersRegistry, IViewDescriptor, IViewsRegistry, ViewContainer, ViewContainerLocation } from 'vs/workbench/common/views';
import { Extensions as ViewContainerExtensions, ICustomTreeViewDescriptor, ICustomViewDescriptor, IViewContainersRegistry, IViewDescriptor, IViewsRegistry, ResolvableTreeItem, ViewContainer, ViewContainerLocation } from 'vs/workbench/common/views';
import { VIEWLET_ID as DEBUG } from 'vs/workbench/contrib/debug/common/debug';
import { VIEWLET_ID as EXPLORER } from 'vs/workbench/contrib/files/common/files';
import { VIEWLET_ID as REMOTE } from 'vs/workbench/contrib/remote/browser/remoteExplorer';
Expand All @@ -29,6 +29,14 @@ import { WebviewViewPane } from 'vs/workbench/contrib/webviewView/browser/webvie
import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionMessageCollector, ExtensionsRegistry, IExtensionPoint, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { IListService, WorkbenchListFocusContextKey } from 'vs/platform/list/browser/listService';
import { IHoverService } from 'vs/workbench/services/hover/browser/hover';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree';
import { ITreeViewsService } from 'vs/workbench/services/views/browser/treeViewsService';
import { HoverPosition } from 'vs/base/browser/ui/hover/hoverWidget';

export interface IUserFriendlyViewsContainerDescriptor {
id: string;
Expand Down Expand Up @@ -255,6 +263,47 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
this.viewsRegistry = Registry.as<IViewsRegistry>(ViewContainerExtensions.ViewsRegistry);
this.handleAndRegisterCustomViewContainers();
this.handleAndRegisterCustomViews();

let showTreeHoverCancellation = new CancellationTokenSource();
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'workbench.action.showTreeHover',
handler: async (accessor: ServicesAccessor, ...args: any[]) => {
showTreeHoverCancellation.cancel();
showTreeHoverCancellation = new CancellationTokenSource();
const listService = accessor.get(IListService);
const treeViewsService = accessor.get(ITreeViewsService);
const hoverService = accessor.get(IHoverService);
const lastFocusedList = listService.lastFocusedList;
if (!(lastFocusedList instanceof AsyncDataTree)) {
return;
}
const focus = lastFocusedList.getFocus();
if (!focus || (focus.length === 0)) {
return;
}
const treeItem = focus[0];

if (treeItem instanceof ResolvableTreeItem) {
await treeItem.resolve(showTreeHoverCancellation.token);
}
if (!treeItem.tooltip) {
return;
}
const element = treeViewsService.getRenderedTreeElement(treeItem);
if (!element) {
return;
}
hoverService.showHover({
content: treeItem.tooltip,
target: element,
hoverPosition: HoverPosition.BELOW,
hideOnHover: false
}, true);
},
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyI),
when: ContextKeyExpr.and(RawCustomTreeViewContextKey, WorkbenchListFocusContextKey)
});
}

private handleAndRegisterCustomViewContainers() {
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/api/common/extHostTreeViews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { IMarkdownString } from 'vs/base/common/htmlContent';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { Command } from 'vs/editor/common/languages';
import { TreeDataTransferConverter, TreeDataTransferDTO } from 'vs/workbench/api/common/shared/treeDataTransfer';
import { ITreeViewsDragAndDropService, TreeViewsDragAndDropService } from 'vs/workbench/services/views/common/treeViewsDragAndDropService';
import { ITreeViewsService, TreeviewsService } from 'vs/workbench/services/views/common/treeViewsService';

type TreeItemHandle = string;

Expand All @@ -50,7 +50,7 @@ function toTreeItemLabel(label: any, extension: IExtensionDescription): ITreeIte
export class ExtHostTreeViews implements ExtHostTreeViewsShape {

private treeViews: Map<string, ExtHostTreeView<any>> = new Map<string, ExtHostTreeView<any>>();
private treeDragAndDropService: ITreeViewsDragAndDropService<vscode.TreeDataTransfer> = new TreeViewsDragAndDropService<vscode.TreeDataTransfer>();
private treeDragAndDropService: ITreeViewsService<vscode.TreeDataTransfer, any, any> = new TreeviewsService<vscode.TreeDataTransfer, any, any>();

constructor(
private _proxy: MainThreadTreeViewsShape,
Expand Down
5 changes: 2 additions & 3 deletions src/vs/workbench/browser/parts/editor/editorDropTarget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ 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';
import { ITreeViewsService } from 'vs/workbench/services/views/browser/treeViewsService';

interface IDropOperation {
splitDirection?: GroupDirection;
Expand Down Expand Up @@ -51,7 +50,7 @@ class DropOverlay extends Themable {
@IInstantiationService private instantiationService: IInstantiationService,
@IEditorService private readonly editorService: IEditorService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@ITreeViewsDragAndDropService private readonly treeViewsDragAndDropService: ITreeViewsDragAndDropService<ITreeDataTransfer>
@ITreeViewsService private readonly treeViewsDragAndDropService: ITreeViewsService
) {
super(themeService);

Expand Down
13 changes: 10 additions & 3 deletions src/vs/workbench/browser/parts/views/treeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ import { isCancellationError } from 'vs/base/common/errors';
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
import { CodeDataTransfers, DraggedTreeItemsIdentifier, fillEditorsDragData, LocalSelectionTransfer } from 'vs/workbench/browser/dnd';
import { Schemas } from 'vs/base/common/network';
import { ITreeViewsDragAndDropService } from 'vs/workbench/services/views/common/treeViewsDragAndDropService';
import { ITreeViewsService } from 'vs/workbench/services/views/browser/treeViewsService';
import { generateUuid } from 'vs/base/common/uuid';
import { ILogService } from 'vs/platform/log/common/log';
import { Mimes } from 'vs/base/common/mime';
Expand Down Expand Up @@ -151,6 +151,8 @@ class Root implements ITreeItem {

const noDataProviderMessage = localize('no-dataprovider', "There is no data provider registered that can provide view data.");

export const RawCustomTreeViewContextKey = new RawContextKey<boolean>('customTreeView', false);

class Tree extends WorkbenchAsyncDataTree<ITreeItem, ITreeItem, FuzzyScore> { }

abstract class AbstractTreeView extends Disposable implements ITreeView {
Expand Down Expand Up @@ -555,6 +557,8 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
renderer.actionRunner = actionRunner;

this.tree.contextKeyService.createKey<boolean>(this.id, true);
const customTreeKey = RawCustomTreeViewContextKey.bindTo(this.tree.contextKeyService);
customTreeKey.set(true);
this._register(this.tree.onContextMenu(e => this.onContextMenu(treeMenus, e, actionRunner)));
this._register(this.tree.onDidChangeSelection(e => this._onDidChangeSelection.fire(e.elements)));
this._register(this.tree.onDidChangeCollapseState(e => {
Expand Down Expand Up @@ -895,7 +899,8 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
@IThemeService private readonly themeService: IThemeService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@ILabelService private readonly labelService: ILabelService,
@IHoverService private readonly hoverService: IHoverService
@IHoverService private readonly hoverService: IHoverService,
@ITreeViewsService private readonly treeViewsService: ITreeViewsService
) {
super();
this._hoverDelegate = {
Expand Down Expand Up @@ -1033,6 +1038,8 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
}
this.setAlignment(templateData.container, node);
disposableStore.add(this.themeService.onDidFileIconThemeChange(() => this.setAlignment(templateData.container, node)));
this.treeViewsService.addRenderedTreeItemElement(node, templateData.container);
disposableStore.add(toDisposable(() => this.treeViewsService.removeRenderedTreeItemElement(node)));
}

private setAlignment(container: HTMLElement, treeItem: ITreeItem) {
Expand Down Expand Up @@ -1265,7 +1272,7 @@ export class CustomTreeViewDragAndDrop implements ITreeDragAndDrop<ITreeItem> {
private readonly treeId: string,
@ILabelService private readonly labelService: ILabelService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@ITreeViewsDragAndDropService private readonly treeViewsDragAndDropService: ITreeViewsDragAndDropService<ITreeDataTransfer>,
@ITreeViewsService private readonly treeViewsDragAndDropService: ITreeViewsService,
@ILogService private readonly logService: ILogService) {
this.treeMimeType = `application/vnd.code.tree.${treeId.toLowerCase()}`;
}
Expand Down
13 changes: 13 additions & 0 deletions src/vs/workbench/services/views/browser/treeViewsService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ITreeDataTransfer, ITreeItem } from 'vs/workbench/common/views';
import { ITreeViewsService as ITreeViewsServiceCommon, TreeviewsService } from 'vs/workbench/services/views/common/treeViewsService';

export interface ITreeViewsService extends ITreeViewsServiceCommon<ITreeDataTransfer, ITreeItem, HTMLElement> { }
export const ITreeViewsService = createDecorator<ITreeViewsService>('treeViewsService');
registerSingleton(ITreeViewsService, TreeviewsService);
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ITreeDataTransfer } from 'vs/workbench/common/views';

export const ITreeViewsDragAndDropService = createDecorator<ITreeViewsDragAndDropService<ITreeDataTransfer>>('treeViewsDragAndDropService');
export interface ITreeViewsDragAndDropService<T> {
export interface ITreeViewsService<T, U, V> {
readonly _serviceBrand: undefined;

removeDragOperationTransfer(uuid: string | undefined): Promise<T | undefined> | undefined;
addDragOperationTransfer(uuid: string, transferPromise: Promise<T | undefined>): void;

getRenderedTreeElement(node: U): V | undefined;
addRenderedTreeItemElement(node: U, element: V): void;
removeRenderedTreeItemElement(node: U): void;
}

export class TreeViewsDragAndDropService<T> implements ITreeViewsDragAndDropService<T> {
export class TreeviewsService<T, U, V> implements ITreeViewsService<T, U, V> {
_serviceBrand: undefined;
private _dragOperations: Map<string, Promise<T | undefined>> = new Map();
private _renderedElements: Map<U, V> = new Map();

removeDragOperationTransfer(uuid: string | undefined): Promise<T | undefined> | undefined {
if ((uuid && this._dragOperations.has(uuid))) {
Expand All @@ -31,6 +31,22 @@ export class TreeViewsDragAndDropService<T> implements ITreeViewsDragAndDropServ
addDragOperationTransfer(uuid: string, transferPromise: Promise<T | undefined>): void {
this._dragOperations.set(uuid, transferPromise);
}
}

registerSingleton(ITreeViewsDragAndDropService, TreeViewsDragAndDropService);

getRenderedTreeElement(node: U): V | undefined {
if (this._renderedElements.has(node)) {
return this._renderedElements.get(node);
}
return undefined;
}

addRenderedTreeItemElement(node: U, element: V): void {
this._renderedElements.set(node, element);
}

removeRenderedTreeItemElement(node: U): void {
if (this._renderedElements.has(node)) {
this._renderedElements.delete(node);
}
}
}

0 comments on commit 25b2357

Please sign in to comment.