Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
23 changes: 20 additions & 3 deletions src/vs/vscode.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6538,11 +6538,28 @@ declare module 'vscode' {
getParent?(element: T): ProviderResult<T>;
}

/**
* Label describing the [Tree item](#TreeItem)
*/
export interface TreeItemLabel {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having this as a separate type means, this will only work when the label is a string, right. Or putting it the other way, highlights will not work when the label is an Uri, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. You can only provide highlights to the labels you contribute. Otherwise it is not correct to allow providing highlights to computed labels.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you can only have highlights for labels you contribute, otherwise it is not correct to allow them for computed labels.


/**
* A human-readable string describing the [Tree item](#TreeItem).
*/
label: string;

/**
* Ranges in the label to highlight.
*/
highlights?: { start: number, end: number }[];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have been using tuples instead of objects so far, e.g valueSelection and ParameterInfo#label use [number,number]


}

export class TreeItem {
/**
* A human-readable string describing this item. When `falsy`, it is derived from [resourceUri](#TreeItem.resourceUri).
* Label describing this item. When `falsy`, it is derived from [resourceUri](#TreeItem.resourceUri).
*/
label?: string;
label?: string | TreeItemLabel;

/**
* Optional id for the tree item that has to be unique across tree. The id is used to preserve the selection and expansion state of the tree item.
Expand Down Expand Up @@ -6605,7 +6622,7 @@ declare module 'vscode' {
* @param label A human-readable string describing this item
* @param collapsibleState [TreeItemCollapsibleState](#TreeItemCollapsibleState) of the tree item. Default is [TreeItemCollapsibleState.None](#TreeItemCollapsibleState.None)
*/
constructor(label: string, collapsibleState?: TreeItemCollapsibleState);
constructor(label: string | TreeItemLabel, collapsibleState?: TreeItemCollapsibleState);

/**
* @param resourceUri The [uri](#Uri) of the resource representing this item.
Expand Down
28 changes: 24 additions & 4 deletions src/vs/workbench/api/node/extHostTreeViews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,35 @@ import { URI } from 'vs/base/common/uri';
import { debounceEvent, Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.protocol';
import { ITreeItem, TreeViewItemHandleArg } from 'vs/workbench/common/views';
import { ITreeItem, TreeViewItemHandleArg, ITreeItemLabel } from 'vs/workbench/common/views';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
import { asThenable } from 'vs/base/common/async';
import { TreeItemCollapsibleState, ThemeIcon } from 'vs/workbench/api/node/extHostTypes';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { isUndefinedOrNull, isString } from 'vs/base/common/types';
import { equals } from 'vs/base/common/arrays';
import { ILogService } from 'vs/platform/log/common/log';

type TreeItemHandle = string;

function toTreeItemLabel(label: any): ITreeItemLabel {
if (isString(label)) {
return { label };
}

if (label
&& typeof label === 'object'
&& typeof label.label === 'string') {
if (Array.isArray(label.highlights) && label.highlights.every(highlight => typeof highlight === 'object' && typeof highlight.start === 'number' && typeof highlight.end === 'number')) {
return label;
} else {
return { label: label.label };
}
}

return void 0;
}


export class ExtHostTreeViews implements ExtHostTreeViewsShape {

private treeViews: Map<string, ExtHostTreeView<any>> = new Map<string, ExtHostTreeView<any>>();
Expand Down Expand Up @@ -383,7 +402,7 @@ class ExtHostTreeView<T> extends Disposable {
const item = {
handle,
parentHandle: parent ? parent.item.handle : void 0,
label: extensionTreeItem.label,
label: toTreeItemLabel(extensionTreeItem.label),
resourceUri: extensionTreeItem.resourceUri,
tooltip: typeof extensionTreeItem.tooltip === 'string' ? extensionTreeItem.tooltip : void 0,
command: extensionTreeItem.command ? this.commands.toInternal(extensionTreeItem.command) : void 0,
Expand All @@ -402,8 +421,9 @@ class ExtHostTreeView<T> extends Disposable {
return `${ExtHostTreeView.ID_HANDLE_PREFIX}/${id}`;
}

const treeItemLabel = toTreeItemLabel(label);
const prefix: string = parent ? parent.item.handle : ExtHostTreeView.LABEL_HANDLE_PREFIX;
let elementId = label ? label : resourceUri ? basename(resourceUri.path) : '';
let elementId = treeItemLabel ? treeItemLabel.label : resourceUri ? basename(resourceUri.path) : '';
elementId = elementId.indexOf('/') !== -1 ? elementId.replace('/', '//') : elementId;
const existingHandle = this.nodes.has(element) ? this.nodes.get(element).item.handle : void 0;
const childrenNodes = (this.getChildrenNodes(parent) || []);
Expand Down
6 changes: 3 additions & 3 deletions src/vs/workbench/api/node/extHostTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1791,16 +1791,16 @@ export enum ProgressLocation {

export class TreeItem {

label?: string;
label?: string | vscode.TreeItemLabel;
resourceUri?: URI;
iconPath?: string | URI | { light: string | URI; dark: string | URI };
command?: vscode.Command;
contextValue?: string;
tooltip?: string;

constructor(label: string, collapsibleState?: vscode.TreeItemCollapsibleState)
constructor(label: string | vscode.TreeItemLabel, collapsibleState?: vscode.TreeItemCollapsibleState)
constructor(resourceUri: URI, collapsibleState?: vscode.TreeItemCollapsibleState)
constructor(arg1: string | URI, public collapsibleState: vscode.TreeItemCollapsibleState = TreeItemCollapsibleState.None) {
constructor(arg1: string | vscode.TreeItemLabel | URI, public collapsibleState: vscode.TreeItemCollapsibleState = TreeItemCollapsibleState.None) {
if (arg1 instanceof URI) {
this.resourceUri = arg1;
} else {
Expand Down
14 changes: 8 additions & 6 deletions src/vs/workbench/browser/parts/views/customView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
import { ContextAwareMenuItemActionItem, fillInActionBarActions, fillInContextMenuActions } from 'vs/platform/actions/browser/menuItemActionItem';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IViewsService, ITreeViewer, ITreeItem, TreeItemCollapsibleState, ITreeViewDataProvider, TreeViewItemHandleArg, ICustomViewDescriptor, ViewsRegistry, ViewContainer } from 'vs/workbench/common/views';
import { IViewsService, ITreeViewer, ITreeItem, TreeItemCollapsibleState, ITreeViewDataProvider, TreeViewItemHandleArg, ICustomViewDescriptor, ViewsRegistry, ViewContainer, ITreeItemLabel } from 'vs/workbench/common/views';
import { IViewletViewOptions, FileIconThemableWorkbenchTree } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { INotificationService } from 'vs/platform/notification/common/notification';
Expand Down Expand Up @@ -164,7 +164,7 @@ class TitleMenus implements IDisposable {
}

class Root implements ITreeItem {
label = 'root';
label = { label: 'root' };
handle = '0';
parentHandle = null;
collapsibleState = TreeItemCollapsibleState.Expanded;
Expand Down Expand Up @@ -513,7 +513,7 @@ class TreeRenderer implements IRenderer {
DOM.addClass(container, 'custom-view-tree-node-item');

const icon = DOM.append(container, DOM.$('.custom-view-tree-node-item-icon'));
const resourceLabel = this.instantiationService.createInstance(ResourceLabel, container, {});
const resourceLabel = this.instantiationService.createInstance(ResourceLabel, container, { supportHighlights: true });
DOM.addClass(resourceLabel.element, 'custom-view-tree-node-item-resourceLabel');
const actionsContainer = DOM.append(resourceLabel.element, DOM.$('.actions'));
const actionBar = new ActionBar(actionsContainer, {
Expand All @@ -526,7 +526,9 @@ class TreeRenderer implements IRenderer {

renderElement(tree: ITree, node: ITreeItem, templateId: string, templateData: ITreeExplorerTemplateData): void {
const resource = node.resourceUri ? URI.revive(node.resourceUri) : null;
const label = node.label ? node.label : resource ? basename(resource.path) : '';
const treeItemLabel: ITreeItemLabel = node.label ? node.label : resource ? { label: basename(resource.path) } : void 0;
const label = treeItemLabel ? treeItemLabel.label : void 0;
const matches = treeItemLabel ? treeItemLabel.highlights : void 0;
const icon = this.themeService.getTheme().type === LIGHT ? node.icon : node.iconDark;
const iconUrl = icon ? URI.revive(icon) : null;
const title = node.tooltip ? node.tooltip : resource ? void 0 : label;
Expand All @@ -537,9 +539,9 @@ class TreeRenderer implements IRenderer {

if (resource || node.themeIcon) {
const fileDecorations = this.configurationService.getValue<{ colors: boolean, badges: boolean }>('explorer.decorations');
templateData.resourceLabel.setLabel({ name: label, resource: resource ? resource : URI.parse('missing:_icon_resource') }, { fileKind: this.getFileKind(node), title, hideIcon: !!iconUrl, fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'] });
templateData.resourceLabel.setLabel({ name: label, resource: resource ? resource : URI.parse('missing:_icon_resource') }, { fileKind: this.getFileKind(node), title, hideIcon: !!iconUrl, fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches });
} else {
templateData.resourceLabel.setLabel({ name: label }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'] });
templateData.resourceLabel.setLabel({ name: label }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches });
}

templateData.icon.style.backgroundImage = iconUrl ? `url('${iconUrl.toString(true)}')` : '';
Expand Down
10 changes: 9 additions & 1 deletion src/vs/workbench/common/views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,14 @@ export enum TreeItemCollapsibleState {
Expanded = 2
}

export interface ITreeItemLabel {

label: string;

highlights?: { start: number, end: number }[];

}

export interface ITreeItem {

handle: string;
Expand All @@ -288,7 +296,7 @@ export interface ITreeItem {

collapsibleState: TreeItemCollapsibleState;

label?: string;
label?: ITreeItemLabel;

icon?: UriComponents;

Expand Down
Loading