From 006361a660aa11af7519b0d080b861711526e40f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 20 Sep 2016 17:26:19 +0200 Subject: [PATCH] share one kind of label class --- src/vs/workbench/browser/labels.ts | 152 ++++++++++++++++++ .../browser/parts/editor/editorLabel.ts | 88 ---------- .../parts/editor/noTabsTitleControl.ts | 2 +- .../browser/parts/editor/tabsTitleControl.ts | 2 +- src/vs/workbench/parts/files/browser/files.ts | 79 --------- .../files/browser/views/explorerViewer.ts | 2 +- .../files/browser/views/openEditorsViewer.ts | 4 +- 7 files changed, 157 insertions(+), 172 deletions(-) create mode 100644 src/vs/workbench/browser/labels.ts delete mode 100644 src/vs/workbench/browser/parts/editor/editorLabel.ts diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts new file mode 100644 index 00000000000..f65b369f91b --- /dev/null +++ b/src/vs/workbench/browser/labels.ts @@ -0,0 +1,152 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import uri from 'vs/base/common/uri'; +import paths = require('vs/base/common/paths'); +import {IconLabel, IIconLabelOptions} from 'vs/base/browser/ui/iconLabel/iconLabel'; +import {IExtensionService} from 'vs/platform/extensions/common/extensions'; +import {IModeService} from 'vs/editor/common/services/modeService'; +import {IEditorInput} from 'vs/platform/editor/common/editor'; +import {getResource} from 'vs/workbench/common/editor'; +import {getPathLabel} from 'vs/base/common/labels'; +import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; + +export interface IEditorLabel { + name: string; + description?: string; + resource?: uri; +} + +export interface IResourceLabelOptions extends IIconLabelOptions { + isFolder?: boolean; +} + +export class ResourceLabel extends IconLabel { + private label: IEditorLabel; + private options: IResourceLabelOptions; + + constructor( + container: HTMLElement, + @IExtensionService private extensionService: IExtensionService, + @IWorkspaceContextService protected contextService: IWorkspaceContextService, + @IModeService private modeService: IModeService + ) { + super(container); + + this.extensionService.onReady().then(() => { + this.render(); // there can be additional modes once the extension host is ready so we need to render again + }); + } + + public setLabel(label: IEditorLabel, options?: IResourceLabelOptions): void { + this.label = label; + this.options = options; + + this.render(); + } + + public clear(): void { + this.label = void 0; + this.options = void 0; + + this.setValue(); + } + + private render(): void { + if (!this.label) { + return; + } + + const resource = this.label.resource; + + let title = ''; + if (this.options && this.options.title) { + title = this.options.title; + } else if (resource) { + title = resource.fsPath; + } + + const extraClasses = this.getIconClasses(resource); + if (this.options && this.options.extraClasses) { + extraClasses.push(...this.options.extraClasses); + } + + const italic = this.options && this.options.italic; + + this.setValue(this.label.name, this.label.description, { title, extraClasses, italic }); + } + + public dispose(): void { + this.label = void 0; + this.options = void 0; + } + + protected getIconClasses(arg1?: uri | string): string[] { + let path: string; + if (typeof arg1 === 'string') { + path = arg1; + } else if (arg1) { + path = arg1.fsPath; + } + + const classes = (this.options && this.options.isFolder) ? ['folder-icon'] : ['file-icon']; + + if (path) { + 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(`${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(path); + if (langId) { + classes.push(`${this.cssEscape(langId)}-lang-file-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 + } +} + +export class EditorLabel extends ResourceLabel { + + public setEditor(editor: IEditorInput, options?: IResourceLabelOptions): void { + this.setLabel({ + resource: getResource(editor), + name: editor.getName(), + description: editor.getDescription() + }, options); + } +} + +export interface IFileLabelOptions extends IResourceLabelOptions { + hidePath?: boolean; +} + +export class FileLabel extends ResourceLabel { + + public setFile(resource: uri, options: IFileLabelOptions = Object.create(null)): void { + this.setLabel({ + resource, + name: paths.basename(resource.fsPath), + description: !options.hidePath ? getPathLabel(paths.dirname(resource.fsPath), this.contextService) : void 0 + }, options); + } +} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/editorLabel.ts b/src/vs/workbench/browser/parts/editor/editorLabel.ts deleted file mode 100644 index 1643bfef1a2..00000000000 --- a/src/vs/workbench/browser/parts/editor/editorLabel.ts +++ /dev/null @@ -1,88 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import uri from 'vs/base/common/uri'; -import {getFileIconClasses} from 'vs/base/browser/ui/fileLabel/fileLabel'; -import {IconLabel, IIconLabelOptions} from 'vs/base/browser/ui/iconLabel/iconLabel'; -import {IExtensionService} from 'vs/platform/extensions/common/extensions'; -import {IModeService} from 'vs/editor/common/services/modeService'; -import {IEditorInput} from 'vs/platform/editor/common/editor'; -import {getResource} from 'vs/workbench/common/editor'; - -export interface IEditorLabel { - name: string; - description?: string; - resource?: uri; -} - -export class EditorLabel extends IconLabel { - private label: IEditorLabel; - private options: IIconLabelOptions; - - constructor( - container: HTMLElement, - @IExtensionService private extensionService: IExtensionService, - @IModeService private modeService: IModeService - ) { - super(container); - - this.extensionService.onReady().then(() => { - this.render(); // there can be additional modes once the extension host is ready so we need to render again - }); - } - - public setInput(input: IEditorInput, options?: IIconLabelOptions): void { - this.setLabel({ - resource: getResource(input), - name: input.getName(), - description: input.getDescription() - }, options); - } - - public setLabel(label: IEditorLabel, options?: IIconLabelOptions): void { - this.label = label; - this.options = options; - - this.render(); - } - - public clear(): void { - this.label = void 0; - this.options = void 0; - - this.setValue(); - } - - private render(): void { - if (!this.label) { - return; - } - - const resource = this.label.resource; - - let title = ''; - if (this.options && this.options.title) { - title = this.options.title; - } else if (resource) { - title = resource.fsPath; - } - - const extraClasses = getFileIconClasses(resource, path => this.modeService.getModeIdByFilenameOrFirstLine(path)); - if (this.options && this.options.extraClasses) { - extraClasses.push(...this.options.extraClasses); - } - - const italic = this.options && this.options.italic; - - this.setValue(this.label.name, this.label.description, { title, extraClasses, italic }); - } - - public dispose(): void { - this.label = void 0; - this.options = void 0; - } -} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index bdd67da247d..ae6694707d6 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -10,7 +10,7 @@ import errors = require('vs/base/common/errors'); import {IEditorGroup, getResource} from 'vs/workbench/common/editor'; import DOM = require('vs/base/browser/dom'); import {TitleControl} from 'vs/workbench/browser/parts/editor/titleControl'; -import {EditorLabel} from 'vs/workbench/browser/parts/editor/editorLabel'; +import {EditorLabel} from 'vs/workbench/browser/labels'; export class NoTabsTitleControl extends TitleControl { private titleContainer: HTMLElement; diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 50e30169a84..debce88bfa2 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -15,7 +15,7 @@ import {Position, IEditorInput} from 'vs/platform/editor/common/editor'; import {IEditorGroup, IEditorIdentifier, asFileEditorInput, getResource} from 'vs/workbench/common/editor'; import {StandardKeyboardEvent} from 'vs/base/browser/keyboardEvent'; import {KeyCode} from 'vs/base/common/keyCodes'; -import {EditorLabel} from 'vs/workbench/browser/parts/editor/editorLabel'; +import {EditorLabel} from 'vs/workbench/browser/labels'; import {ActionBar} from 'vs/base/browser/ui/actionbar/actionbar'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; diff --git a/src/vs/workbench/parts/files/browser/files.ts b/src/vs/workbench/parts/files/browser/files.ts index 0fab422eb48..fd8b85e2e49 100644 --- a/src/vs/workbench/parts/files/browser/files.ts +++ b/src/vs/workbench/parts/files/browser/files.ts @@ -4,16 +4,8 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import uri from 'vs/base/common/uri'; -import paths = require('vs/base/common/paths'); import {EditorDescriptor} from 'vs/workbench/browser/parts/editor/baseEditor'; import {IFileEditorDescriptor} from 'vs/workbench/parts/files/common/files'; -import {getFileIconClasses} from 'vs/base/browser/ui/fileLabel/fileLabel'; -import {IconLabel, IIconLabelOptions} from 'vs/base/browser/ui/iconLabel/iconLabel'; -import {IExtensionService} from 'vs/platform/extensions/common/extensions'; -import {IModeService} from 'vs/editor/common/services/modeService'; -import {getPathLabel} from 'vs/base/common/labels'; -import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; /** * A lightweight descriptor of an editor for files. Optionally allows to specify a list of mime types the editor @@ -32,75 +24,4 @@ export class FileEditorDescriptor extends EditorDescriptor implements IFileEdito public getMimeTypes(): string[] { return this.mimetypes; } -} - -export interface IFileIconLabelOptions extends IIconLabelOptions { - hidePath?: boolean; - isFolder?: boolean; -} - -export class FileLabel extends IconLabel { - private file: uri; - private options: IFileIconLabelOptions; - - constructor( - container: HTMLElement, - @IExtensionService private extensionService: IExtensionService, - @IWorkspaceContextService private contextService: IWorkspaceContextService, - @IModeService private modeService: IModeService - ) { - super(container); - - this.extensionService.onReady().then(() => { - this.render(); // there can be additional modes once the extension host is ready so we need to render again - }); - } - - public setFile(resource: uri, options?: IFileIconLabelOptions): void { - this.file = resource; - this.options = options; - - this.render(); - } - - public clear(): void { - this.file = void 0; - this.options = void 0; - - this.setValue(); - } - - private render(): void { - if (!this.file) { - return; - } - - const label = paths.basename(this.file.fsPath); - - let description: string; - if (!this.options || !this.options.hidePath) { - description = getPathLabel(paths.dirname(this.file.fsPath), this.contextService); - } - - let title = ''; - if (this.options && this.options.title) { - title = this.options.title; - } else if (this.file) { - title = this.file.fsPath; - } - - const extraClasses = getFileIconClasses(this.file, path => this.modeService.getModeIdByFilenameOrFirstLine(path), this.options && this.options.isFolder); - if (this.options && this.options.extraClasses) { - extraClasses.push(...this.options.extraClasses); - } - - const italic = this.options && this.options.italic; - - this.setValue(label, description, { title, extraClasses, italic }); - } - - public dispose(): void { - this.file = void 0; - this.options = void 0; - } } \ No newline at end of file diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index e435d1cb3f3..a09a64e28db 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -21,7 +21,7 @@ import {InputBox} from 'vs/base/browser/ui/inputbox/inputBox'; import {$, Builder} from 'vs/base/browser/builder'; import platform = require('vs/base/common/platform'); import glob = require('vs/base/common/glob'); -import {FileLabel} from 'vs/workbench/parts/files/browser/files'; +import {FileLabel} from 'vs/workbench/browser/labels'; import {IDisposable} from 'vs/base/common/lifecycle'; import {ContributableActionProvider} from 'vs/workbench/browser/actionBarRegistry'; import {LocalFileChangeEvent, IFilesConfiguration, ITextFileService} from 'vs/workbench/parts/files/common/files'; diff --git a/src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts b/src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts index 140edc11500..571f5b99631 100644 --- a/src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts @@ -8,7 +8,7 @@ import uri from 'vs/base/common/uri'; import errors = require('vs/base/common/errors'); import {TPromise} from 'vs/base/common/winjs.base'; import {IAction} from 'vs/base/common/actions'; -import {EditorLabel} from 'vs/workbench/browser/parts/editor/editorLabel'; +import {EditorLabel} from 'vs/workbench/browser/labels'; import treedefaults = require('vs/base/parts/tree/browser/treeDefaults'); import {IDataSource, ITree, IAccessibilityProvider, IDragAndDropData, IDragOverReaction, DRAG_OVER_ACCEPT, DRAG_OVER_REJECT, ContextMenuEvent, IRenderer} from 'vs/base/parts/tree/browser/tree'; import {ExternalElementsDragAndDropData, ElementsDragAndDropData, DesktopDragAndDropData} from 'vs/base/parts/tree/browser/treeDnd'; @@ -178,7 +178,7 @@ export class Renderer implements IRenderer { private renderOpenEditor(tree: ITree, editor: OpenEditor, templateData: IOpenEditorTemplateData): void { editor.isDirty() ? dom.addClass(templateData.container, 'dirty') : dom.removeClass(templateData.container, 'dirty'); - templateData.root.setInput(editor.editorInput, { italic: editor.isPreview(), extraClasses: ['open-editor'] }); + templateData.root.setEditor(editor.editorInput, { italic: editor.isPreview(), extraClasses: ['open-editor'] }); templateData.actionBar.context = { group: editor.editorGroup, editor: editor.editorInput }; }