Merge pull request #43261 from vbfox/file_as_folder_in_custom_tree

Allow extensions to specify custom tree view resoure type
This commit is contained in:
Sandeep Somavarapu
2018-02-26 10:45:56 +01:00
committed by GitHub
6 changed files with 72 additions and 15 deletions

27
src/vs/vscode.d.ts vendored
View File

@@ -5063,6 +5063,25 @@ declare module 'vscode' {
getChildren(element?: T): ProviderResult<T[]>;
}
/**
* A category in a File Icon Theme, either [file](#ThemeIcon.file) or [folder](#ThemeIcon.folder)
*/
export class ThemeIcon {
/**
* Use the File Icon Theme for files
*/
static readonly File: ThemeIcon;
/**
* Use the File Icon Theme for files
*/
static readonly Folder: ThemeIcon;
readonly id: string;
private constructor(id: string);
}
export class TreeItem {
/**
* A human-readable string describing this item. When `falsy`, it is derived from [resourceUri](#TreeItem.resourceUri).
@@ -5077,15 +5096,17 @@ declare module 'vscode' {
id?: string;
/**
* The icon path for the tree item. When `falsy`, it is derived from [resourceUri](#TreeItem.resourceUri).
* The icon path for the tree item.
* When `falsy` it is derived from [resourceUri](#TreeItem.resourceUri) and the current theme (As a file if the node isn't collapsible or for folders otherwise)
* When a [ThemeIcon](#ThemeIcon) is specified it is derived from [resourceUri](#TreeItem.resourceUri) and the current theme for the specified category.
*/
iconPath?: string | Uri | { light: string | Uri; dark: string | Uri };
iconPath?: string | Uri | { light: string | Uri | ThemeIcon; dark: string | Uri | ThemeIcon } | ThemeIcon;
/**
* The [uri](#Uri) of the resource representing this item.
*
* Will be used to derive the [label](#TreeItem.label), when it is not provided.
* Will be used to derive the icon from current file icon theme, when [iconPath](#TreeItem.iconPath) is not provided.
* Will be used to derive the icon from current icon theme, when [iconPath](#TreeItem.iconPath) is not provided or is a [ThemeIcon](#ThemeIcon).
*/
resourceUri?: Uri;

View File

@@ -623,6 +623,7 @@ export function createApiFactory(
WorkspaceEdit: extHostTypes.WorkspaceEdit,
ProgressLocation: extHostTypes.ProgressLocation,
TreeItemCollapsibleState: extHostTypes.TreeItemCollapsibleState,
ThemeIcon: extHostTypes.ThemeIcon,
TreeItem: extHostTypes.TreeItem,
ThemeColor: extHostTypes.ThemeColor,
// functions

View File

@@ -12,10 +12,10 @@ import { debounceEvent } from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
import { Disposable } from 'vs/base/common/lifecycle';
import { ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.protocol';
import { ITreeItem, TreeViewItemHandleArg } from 'vs/workbench/common/views';
import { ITreeItem, TreeViewItemHandleArg, IThemeIcon } from 'vs/workbench/common/views';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
import { asWinJsPromise } from 'vs/base/common/async';
import { TreeItemCollapsibleState } from 'vs/workbench/api/node/extHostTypes';
import { TreeItemCollapsibleState, ThemeIcon } from 'vs/workbench/api/node/extHostTypes';
import { isUndefinedOrNull } from 'vs/base/common/types';
type TreeItemHandle = string;
@@ -315,9 +315,11 @@ class ExtHostTreeView<T> extends Disposable {
throw new Error('This should not be reached');
}
private getLightIconPath(extensionTreeItem: vscode.TreeItem): string {
private getLightIconPath(extensionTreeItem: vscode.TreeItem): string | IThemeIcon {
if (extensionTreeItem.iconPath) {
if (typeof extensionTreeItem.iconPath === 'string' || extensionTreeItem.iconPath instanceof URI) {
if (typeof extensionTreeItem.iconPath === 'string'
|| extensionTreeItem.iconPath instanceof URI
|| extensionTreeItem.iconPath instanceof ThemeIcon) {
return this.getIconPath(extensionTreeItem.iconPath);
}
return this.getIconPath(extensionTreeItem.iconPath['light']);
@@ -325,17 +327,20 @@ class ExtHostTreeView<T> extends Disposable {
return void 0;
}
private getDarkIconPath(extensionTreeItem: vscode.TreeItem): string {
private getDarkIconPath(extensionTreeItem: vscode.TreeItem): string | IThemeIcon {
if (extensionTreeItem.iconPath && extensionTreeItem.iconPath['dark']) {
return this.getIconPath(extensionTreeItem.iconPath['dark']);
}
return void 0;
}
private getIconPath(iconPath: string | URI): string {
private getIconPath(iconPath: string | URI | ThemeIcon): string | IThemeIcon {
if (iconPath instanceof URI) {
return iconPath.toString();
}
if (iconPath instanceof ThemeIcon) {
return { id: iconPath.id };
}
return URI.file(iconPath).toString();
}

View File

@@ -1544,6 +1544,18 @@ export enum TreeItemCollapsibleState {
Expanded = 2
}
export class ThemeIcon {
static readonly File = new ThemeIcon('file');
static readonly Folder = new ThemeIcon('folder');
readonly id: string;
private constructor(id: string) {
this.id = id;
}
}
export class ThemeColor {
id: string;
constructor(id: string) {

View File

@@ -13,7 +13,7 @@ import * as DOM from 'vs/base/browser/dom';
import { $ } from 'vs/base/browser/builder';
import { LIGHT } from 'vs/platform/theme/common/themeService';
import { ITree, IDataSource, IRenderer, ContextMenuEvent } from 'vs/base/parts/tree/browser/tree';
import { TreeItemCollapsibleState, ITreeItem, ITreeViewer, ICustomViewsService, ITreeViewDataProvider, ViewsRegistry, IViewDescriptor, TreeViewItemHandleArg, ICustomViewDescriptor, IViewsViewlet } from 'vs/workbench/common/views';
import { TreeItemCollapsibleState, ITreeItem, ITreeViewer, ICustomViewsService, ITreeViewDataProvider, ViewsRegistry, IViewDescriptor, TreeViewItemHandleArg, ICustomViewDescriptor, IViewsViewlet, FileThemeIconId, FolderThemeIconId } from 'vs/workbench/common/views';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress';
@@ -447,8 +447,19 @@ class TreeRenderer implements IRenderer {
DOM.removeClass(templateData.label, 'custom-view-tree-node-item-label');
DOM.removeClass(templateData.resourceLabel.element, 'custom-view-tree-node-item-resourceLabel');
if (resource && !icon) {
templateData.resourceLabel.setLabel({ name: label, resource }, { fileKind: node.collapsibleState === TreeItemCollapsibleState.Collapsed || node.collapsibleState === TreeItemCollapsibleState.Expanded ? FileKind.FOLDER : FileKind.FILE, title: node.tooltip });
if (resource && (typeof icon !== 'string')) {
let fileKind = node.collapsibleState === TreeItemCollapsibleState.Collapsed || node.collapsibleState === TreeItemCollapsibleState.Expanded ? FileKind.FOLDER : FileKind.FILE;
if (icon && icon.id) {
switch (icon.id) {
case FileThemeIconId:
fileKind = FileKind.FILE;
break;
case FolderThemeIconId:
fileKind = FileKind.FOLDER;
break;
}
}
templateData.resourceLabel.setLabel({ name: label, resource }, { fileKind, title: node.tooltip });
DOM.addClass(templateData.resourceLabel.element, 'custom-view-tree-node-item-resourceLabel');
} else {
templateData.label.textContent = label;
@@ -494,7 +505,7 @@ class TreeItemIcon extends Disposable {
const fileIconTheme = this.themeService.getFileIconTheme();
const contributedIcon = this.themeService.getTheme().type === LIGHT ? this._treeItem.icon : this._treeItem.iconDark;
const hasContributedIcon = !!contributedIcon;
const hasContributedIcon = typeof contributedIcon === 'string';
const hasChildren = this._treeItem.collapsibleState !== TreeItemCollapsibleState.None;
const hasResource = !!this._treeItem.resourceUri;
const isFolder = hasResource && hasChildren;

View File

@@ -202,6 +202,13 @@ export enum TreeItemCollapsibleState {
Expanded = 2
}
export const FileThemeIconId = 'file';
export const FolderThemeIconId = 'folder';
export interface IThemeIcon {
readonly id: string;
}
export interface ITreeItem {
handle: string;
@@ -212,9 +219,9 @@ export interface ITreeItem {
label?: string;
icon?: string;
icon?: string | IThemeIcon;
iconDark?: string;
iconDark?: string | IThemeIcon;
resourceUri?: UriComponents;