From 67fb63d2e4ebf084094da63c7d06441f5dee1c45 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 20 Sep 2016 10:43:59 +0200 Subject: [PATCH] icons: extract CSS class computation to helper --- src/vs/base/browser/ui/fileLabel/fileLabel.ts | 56 ++++++++++++++++--- .../parts/files/browser/views/explorerView.ts | 2 +- .../files/browser/views/explorerViewer.ts | 49 ++-------------- 3 files changed, 52 insertions(+), 55 deletions(-) diff --git a/src/vs/base/browser/ui/fileLabel/fileLabel.ts b/src/vs/base/browser/ui/fileLabel/fileLabel.ts index 9d190fa78b1..e2ac0ced0a1 100644 --- a/src/vs/base/browser/ui/fileLabel/fileLabel.ts +++ b/src/vs/base/browser/ui/fileLabel/fileLabel.ts @@ -14,18 +14,17 @@ import { IMatch } from 'vs/base/common/filters'; import {IWorkspaceProvider, getPathLabel} from 'vs/base/common/labels'; export class FileLabel { - private domNode: HTMLElement; private labelNode: HighlightedLabel; private directoryNode: HTMLElement; private basepath: string; private path: string; - private labelHighlights: IMatch[]= []; + private labelHighlights: IMatch[] = []; constructor(container: HTMLElement, arg2?: uri | string, arg3?: uri | string | IWorkspaceProvider) { this.domNode = dom.append(container, dom.$('.monaco-file-label')); - this.labelNode= new HighlightedLabel(dom.append(this.domNode, dom.$('span.file-name'))); - this.directoryNode= dom.append(this.domNode, dom.$('span.file-path')); + this.labelNode = new HighlightedLabel(dom.append(this.domNode, dom.$('span.file-name'))); + this.directoryNode = dom.append(this.domNode, dom.$('span.file-path')); if (arg3) { this.basepath = getPath(arg3); @@ -41,17 +40,19 @@ export class FileLabel { } public setValue(arg1: uri | string, labelHighlights?: IMatch[]): void { - let newPath = getPath(arg1); + const newPath = getPath(arg1); + this.path = newPath; - this.labelHighlights= labelHighlights; + this.labelHighlights = labelHighlights; this.render(); } private render(): void { this.domNode.title = this.path; this.labelNode.set(paths.basename(this.path), this.labelHighlights); - let parent = paths.dirname(this.path); - this.directoryNode.textContent= parent && parent !== '.' ? getPathLabel(parent, this.basepath) : ''; + + const parent = paths.dirname(this.path); + this.directoryNode.textContent = parent && parent !== '.' ? getPathLabel(parent, this.basepath) : ''; } } @@ -65,9 +66,46 @@ function getPath(arg1: uri | string | IWorkspaceProvider): string { } if (types.isFunction((arg1).getWorkspace)) { - let ws = (arg1).getWorkspace(); + const ws = (arg1).getWorkspace(); return ws ? ws.resource.fsPath : void 0; } return (arg1).fsPath; +} + +export function getFileIconClasses(arg1: uri | string, getLanguageId: (path: string) => string, isFolder?: boolean): string[] { + let path: string; + if (typeof arg1 === 'string') { + path = arg1; + } else { + path = arg1.fsPath; + } + + const classes = isFolder ? ['folder-icon'] : ['file-icon']; + + const basename = paths.basename(path); + const dotSegments = basename.split('.'); + + const name = dotSegments[0]; // file.txt => "file", .dockerfile => "", file.some.txt => "file" + if (name) { + classes.push(`${cssEscape(name.toLowerCase())}-name-file-icon`); + } + + const extensions = dotSegments.splice(1); + if (extensions.length > 0) { + for (let i = 0; i < extensions.length; i++) { + classes.push(`${cssEscape(extensions.slice(i).join('.').toLowerCase())}-ext-file-icon`); // add each combination of all found extensions if more than one + } + } + + const langId = getLanguageId(path); + if (langId) { + classes.push(`${cssEscape(langId)}-lang-file-icon`); + } + + return classes; +} + +function cssEscape(val: string): string { + return val.replace(/\s/g, '\\$&'); // make sure to not introduce CSS classes from files that contain whitespace } \ No newline at end of file diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index 30915746219..e50f253006d 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -117,7 +117,7 @@ export class ExplorerView extends CollapsibleViewletView { public renderBody(container: HTMLElement): void { this.treeContainer = super.renderViewTree(container); DOM.addClass(this.treeContainer, 'explorer-folders-view'); - DOM.addClass(this.treeContainer, 'show-file-icons'); // enable to show file icons if configured + DOM.addClass(this.treeContainer, 'show-file-icons'); this.tree = this.createViewer($(this.treeContainer)); diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 75a7d339cb9..cb86320d7b0 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -14,6 +14,7 @@ import {MIME_BINARY} from 'vs/base/common/mime'; import async = require('vs/base/common/async'); import paths = require('vs/base/common/paths'); import errors = require('vs/base/common/errors'); +import {getFileIconClasses} from 'vs/base/browser/ui/fileLabel/fileLabel'; import {isString} from 'vs/base/common/types'; import {IAction, ActionRunner as BaseActionRunner, IActionRunner} from 'vs/base/common/actions'; import comparers = require('vs/base/common/comparers'); @@ -295,7 +296,7 @@ export class FileRenderer extends ActionsRenderer implements IRenderer { const fileItem = $(fileItems.item(i)); const resourcePath = fileItem.getProperty(FileRenderer.RESOURCE_PATH_KEY); if (resourcePath) { - fileItem.setClass(['explorer-item', ...this.fileIconClasses(resourcePath)].join(' ')); + fileItem.setClass(['explorer-item', ...getFileIconClasses(resourcePath, path => this.modeService.getModeIdByFilenameOrFirstLine(path))].join(' ')); fileItem.removeProperty(FileRenderer.RESOURCE_PATH_KEY); } } @@ -312,9 +313,9 @@ export class FileRenderer extends ActionsRenderer implements IRenderer { // Item Container const item = $('.explorer-item'); if (stat.isDirectory || (stat instanceof NewStatPlaceholder && stat.isDirectoryPlaceholder())) { - item.addClass(...this.folderIconClasses(stat.resource.fsPath)); + item.addClass(...getFileIconClasses(stat.resource, path => this.modeService.getModeIdByFilenameOrFirstLine(path), true)); } else { - item.addClass(...this.fileIconClasses(stat.resource.fsPath)); + item.addClass(...getFileIconClasses(stat.resource, path => this.modeService.getModeIdByFilenameOrFirstLine(path))); // We need to re-apply the icon CSS classes once the extension host is ready if (!this.extensionsReady) { @@ -390,48 +391,6 @@ export class FileRenderer extends ActionsRenderer implements IRenderer { return () => done(true); } - - private fileIconClasses(fsPath: string): string[] { - const classes = ['file-icon']; - - const basename = paths.basename(fsPath); - const dotSegments = basename.split('.'); - - const name = dotSegments[0]; // file.txt => "file", .dockerfile => "", file.some.txt => "file" - if (name) { - classes.push(`${this.cssEscape(name.toLowerCase())}-name-file-icon`); - } - - const extensions = dotSegments.splice(1); - if (extensions.length > 0) { - for (let i = 0; i < extensions.length; i++) { - classes.push(`${this.cssEscape(extensions.slice(i).join('.').toLowerCase())}-ext-file-icon`); // add each combination of all found extensions if more than one - } - } - - const langId = this.modeService.getModeIdByFilenameOrFirstLine(fsPath); - if (langId) { - classes.push(`${this.cssEscape(langId)}-lang-file-icon`); - } - - return classes; - } - - private folderIconClasses(fsPath: string): string[] { - const basename = paths.basename(fsPath); - - const classes = ['folder-icon']; - - if (basename) { - classes.push(`${this.cssEscape(basename.toLowerCase())}-name-folder-icon`); - } - - return classes; - } - - private cssEscape(val: string): string { - return val.replace(/\s/g, '\\$&'); // make sure to not introduce CSS classes from files that contain whitespace - } } // Explorer Accessibility Provider -- GitLab