mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-23 00:29:35 +01:00
icons: in editor picker
This commit is contained in:
@@ -13,6 +13,7 @@ import {ITree, IElementCallback} from 'vs/base/parts/tree/browser/tree';
|
||||
import filters = require('vs/base/common/filters');
|
||||
import strings = require('vs/base/common/strings');
|
||||
import paths = require('vs/base/common/paths');
|
||||
import {IconLabel, IIconLabelOptions} from 'vs/base/browser/ui/iconLabel/iconLabel';
|
||||
import {IQuickNavigateConfiguration, IModel, IDataSource, IFilter, IAccessiblityProvider, IRenderer, IRunner, Mode} from 'vs/base/parts/quickopen/common/quickOpen';
|
||||
import {IActionProvider} from 'vs/base/parts/tree/browser/actionsRenderer';
|
||||
import {Action, IAction, IActionRunner} from 'vs/base/common/actions';
|
||||
@@ -73,6 +74,13 @@ export class QuickOpenEntry {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The options for the label to use for this entry
|
||||
*/
|
||||
public getLabelOptions(): IIconLabelOptions {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The label of the entry to use when a screen reader wants to read about the entry
|
||||
*/
|
||||
@@ -109,13 +117,6 @@ export class QuickOpenEntry {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra CSS class name to add to the quick open entry to do custom styling of entries.
|
||||
*/
|
||||
public getExtraClass(): string {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to reuse the same model while filtering. Hidden entries will not show up in the viewer.
|
||||
*/
|
||||
@@ -331,6 +332,10 @@ export class QuickOpenEntryGroup extends QuickOpenEntry {
|
||||
return this.entry ? this.entry.getLabel() : super.getLabel();
|
||||
}
|
||||
|
||||
public getLabelOptions(): IIconLabelOptions {
|
||||
return this.entry ? this.entry.getLabelOptions() : super.getLabelOptions();
|
||||
}
|
||||
|
||||
public getAriaLabel(): string {
|
||||
return this.entry ? this.entry.getAriaLabel() : super.getAriaLabel();
|
||||
}
|
||||
@@ -359,10 +364,6 @@ export class QuickOpenEntryGroup extends QuickOpenEntry {
|
||||
return this.entry ? this.entry.getHighlights() : super.getHighlights();
|
||||
}
|
||||
|
||||
public getExtraClass(): string {
|
||||
return this.entry ? this.entry.getExtraClass() : super.getExtraClass();
|
||||
}
|
||||
|
||||
public isHidden(): boolean {
|
||||
return this.entry ? this.entry.isHidden() : super.isHidden();
|
||||
}
|
||||
@@ -426,7 +427,7 @@ export interface IQuickOpenEntryTemplateData {
|
||||
container: HTMLElement;
|
||||
entry: HTMLElement;
|
||||
icon: HTMLSpanElement;
|
||||
label: HighlightedLabel;
|
||||
label: IconLabel;
|
||||
detail: HighlightedLabel;
|
||||
description: HighlightedLabel;
|
||||
actionBar: ActionBar;
|
||||
@@ -510,7 +511,7 @@ class Renderer implements IRenderer<QuickOpenEntry> {
|
||||
entry.appendChild(icon);
|
||||
|
||||
// Label
|
||||
const label = new HighlightedLabel(entry);
|
||||
const label = new IconLabel(entry, { supportHighlights: true });
|
||||
|
||||
// Description
|
||||
const descriptionContainer = document.createElement('span');
|
||||
@@ -585,20 +586,14 @@ class Renderer implements IRenderer<QuickOpenEntry> {
|
||||
if (entry instanceof QuickOpenEntry) {
|
||||
const [labelHighlights, descriptionHighlights, detailHighlights] = entry.getHighlights();
|
||||
|
||||
// Extra Class
|
||||
const extraClass = entry.getExtraClass();
|
||||
if (extraClass) {
|
||||
DOM.addClass(data.entry, extraClass);
|
||||
} else {
|
||||
data.entry.className = 'quick-open-entry';
|
||||
}
|
||||
|
||||
// Icon
|
||||
const iconClass = entry.getIcon() ? ('quick-open-entry-icon ' + entry.getIcon()) : '';
|
||||
data.icon.className = iconClass;
|
||||
|
||||
// Label
|
||||
data.label.set(entry.getLabel(), labelHighlights || []);
|
||||
const options:IIconLabelOptions = entry.getLabelOptions() || Object.create(null);
|
||||
options.matches = labelHighlights || [];
|
||||
data.label.setValue(entry.getLabel(), null, options);
|
||||
|
||||
// Meta
|
||||
data.detail.set(entry.getDetail(), detailHighlights);
|
||||
|
||||
@@ -108,7 +108,7 @@ export class QuickOpenWidget implements IModelProvider {
|
||||
this.model = null;
|
||||
}
|
||||
|
||||
getModel(): IModel<any> {
|
||||
public getModel(): IModel<any> {
|
||||
return this.model;
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ export class QuickOpenWidget implements IModelProvider {
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
public create(): void {
|
||||
public create(): HTMLElement {
|
||||
this.builder = $().div((div: Builder) => {
|
||||
|
||||
// Eventing
|
||||
@@ -300,6 +300,8 @@ export class QuickOpenWidget implements IModelProvider {
|
||||
if (this.layoutDimensions) {
|
||||
this.layout(this.layoutDimensions);
|
||||
}
|
||||
|
||||
return this.builder.getHTMLElement();
|
||||
}
|
||||
|
||||
private onType(): void {
|
||||
|
||||
@@ -80,7 +80,7 @@ export class ResourceLabel extends IconLabel {
|
||||
title = resource.fsPath;
|
||||
}
|
||||
|
||||
const extraClasses = this.getIconClasses(resource);
|
||||
const extraClasses = getIconClasses(this.modeService, resource, this.options && this.options.isFolder);
|
||||
if (this.options && this.options.extraClasses) {
|
||||
extraClasses.push(...this.options.extraClasses);
|
||||
}
|
||||
@@ -91,45 +91,6 @@ export class ResourceLabel extends IconLabel {
|
||||
this.setValue(this.label.name, this.label.description, { title, extraClasses, italic, matches });
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
@@ -164,4 +125,43 @@ export class FileLabel extends ResourceLabel {
|
||||
description: !options.hidePath ? getPathLabel(paths.dirname(resource.fsPath), this.contextService) : void 0
|
||||
}, options);
|
||||
}
|
||||
}
|
||||
|
||||
export function getIconClasses(modeService: IModeService, arg1?: uri | string, isFolder?: boolean): string[] {
|
||||
let path: string;
|
||||
if (typeof arg1 === 'string') {
|
||||
path = arg1;
|
||||
} else if (arg1) {
|
||||
path = arg1.fsPath;
|
||||
}
|
||||
|
||||
const classes = 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(`${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 = modeService.getModeIdByFilenameOrFirstLine(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
|
||||
}
|
||||
@@ -11,9 +11,12 @@ import labels = require('vs/base/common/labels');
|
||||
import URI from 'vs/base/common/uri';
|
||||
import errors = require('vs/base/common/errors');
|
||||
import strings = require('vs/base/common/strings');
|
||||
import {IIconLabelOptions} from 'vs/base/browser/ui/iconLabel/iconLabel';
|
||||
import {IAutoFocus, Mode, IEntryRunContext, IQuickNavigateConfiguration} from 'vs/base/parts/quickopen/common/quickOpen';
|
||||
import {QuickOpenModel, QuickOpenEntry, QuickOpenEntryGroup} from 'vs/base/parts/quickopen/browser/quickOpenModel';
|
||||
import scorer = require('vs/base/common/scorer');
|
||||
import {IModeService} from 'vs/editor/common/services/modeService';
|
||||
import {getIconClasses} from 'vs/workbench/browser/labels';
|
||||
import {QuickOpenHandler} from 'vs/workbench/browser/quickopen';
|
||||
import {Position} from 'vs/platform/editor/common/editor';
|
||||
import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService';
|
||||
@@ -29,6 +32,7 @@ export class EditorPickerEntry extends QuickOpenEntryGroup {
|
||||
private editor: EditorInput,
|
||||
private _group: IEditorGroup,
|
||||
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
|
||||
@IModeService private modeService: IModeService,
|
||||
@IEditorGroupService private editorGroupService: IEditorGroupService
|
||||
) {
|
||||
super();
|
||||
@@ -36,14 +40,21 @@ export class EditorPickerEntry extends QuickOpenEntryGroup {
|
||||
this.stacks = editorGroupService.getStacksModel();
|
||||
}
|
||||
|
||||
public getIcon(): string {
|
||||
return this.editor.isDirty() ? 'dirty' : '';
|
||||
public getLabelOptions(): IIconLabelOptions {
|
||||
return {
|
||||
extraClasses: getIconClasses(this.modeService, this.getResource()),
|
||||
italic: this._group.isPreview(this.editor)
|
||||
};
|
||||
}
|
||||
|
||||
public getLabel(): string {
|
||||
return this.editor.getName();
|
||||
}
|
||||
|
||||
public getIcon(): string {
|
||||
return this.editor.isDirty() ? 'dirty' : '';
|
||||
}
|
||||
|
||||
public get group(): IEditorGroup {
|
||||
return this._group;
|
||||
}
|
||||
@@ -62,10 +73,6 @@ export class EditorPickerEntry extends QuickOpenEntryGroup {
|
||||
return this.editor.getDescription();
|
||||
}
|
||||
|
||||
public getExtraClass(): string {
|
||||
return this._group.isPreview(this.editor) ? 'editor-preview' : '';
|
||||
}
|
||||
|
||||
public run(mode: Mode, context: IEntryRunContext): boolean {
|
||||
if (mode === Mode.OPEN) {
|
||||
return this.runOpen(context);
|
||||
|
||||
@@ -12,6 +12,7 @@ import nls = require('vs/nls');
|
||||
import {Dimension, withElementById} from 'vs/base/browser/builder';
|
||||
import strings = require('vs/base/common/strings');
|
||||
import filters = require('vs/base/common/filters');
|
||||
import DOM = require('vs/base/browser/dom');
|
||||
import URI from 'vs/base/common/uri';
|
||||
import uuid = require('vs/base/common/uuid');
|
||||
import types = require('vs/base/common/types');
|
||||
@@ -514,7 +515,8 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe
|
||||
this.telemetryService
|
||||
);
|
||||
|
||||
this.quickOpenWidget.create();
|
||||
const quickOpenContainer = this.quickOpenWidget.create();
|
||||
DOM.addClass(quickOpenContainer, 'show-file-icons');
|
||||
}
|
||||
|
||||
// Layout
|
||||
|
||||
Reference in New Issue
Block a user