未验证 提交 8bb358f2 编写于 作者: J Joao Moreno

wip: icon label supports multiple labels

上级 65b57bcd
......@@ -24,6 +24,7 @@ export interface IIconLabelValueOptions {
matches?: IMatch[];
labelEscapeNewLines?: boolean;
descriptionMatches?: IMatch[];
readonly separator?: string;
}
class FastLabelNode {
......@@ -86,9 +87,10 @@ class FastLabelNode {
}
export class IconLabel extends Disposable {
private domNode: FastLabelNode;
private labelDescriptionContainer: FastLabelNode;
private labelNode: FastLabelNode | HighlightedLabel;
private descriptionContainer: FastLabelNode;
private nameNode: Label | LabelWithHighlights;
private descriptionNode: FastLabelNode | HighlightedLabel | undefined;
private descriptionNodeFactory: () => FastLabelNode | HighlightedLabel;
......@@ -97,18 +99,21 @@ export class IconLabel extends Disposable {
this.domNode = this._register(new FastLabelNode(dom.append(container, dom.$('.monaco-icon-label'))));
this.labelDescriptionContainer = this._register(new FastLabelNode(dom.append(this.domNode.element, dom.$('.monaco-icon-label-description-container'))));
const labelContainer = dom.append(this.domNode.element, dom.$('.monaco-icon-label-container'));
const nameContainer = dom.append(labelContainer, dom.$('span.monaco-icon-name-container'));
this.descriptionContainer = this._register(new FastLabelNode(dom.append(labelContainer, dom.$('span.monaco-icon-description-container'))));
if (options?.supportHighlights) {
this.labelNode = new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name')), !!options.supportCodicons);
this.nameNode = new LabelWithHighlights(nameContainer, !!options.supportCodicons);
} else {
this.labelNode = this._register(new FastLabelNode(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name'))));
this.nameNode = new Label(nameContainer);
}
if (options?.supportDescriptionHighlights) {
this.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description')), !!options.supportCodicons);
this.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.descriptionContainer.element, dom.$('span.label-description')), !!options.supportCodicons);
} else {
this.descriptionNodeFactory = () => this._register(new FastLabelNode(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description'))));
this.descriptionNodeFactory = () => this._register(new FastLabelNode(dom.append(this.descriptionContainer.element, dom.$('span.label-description'))));
}
}
......@@ -116,7 +121,7 @@ export class IconLabel extends Disposable {
return this.domNode.element;
}
setLabel(label: string, description?: string, options?: IIconLabelValueOptions): void {
setLabel(label: string | string[], description?: string, options?: IIconLabelValueOptions): void {
const classes = ['monaco-icon-label'];
if (options) {
if (options.extraClasses) {
......@@ -131,11 +136,7 @@ export class IconLabel extends Disposable {
this.domNode.className = classes.join(' ');
this.domNode.title = options?.title || '';
if (this.labelNode instanceof HighlightedLabel) {
this.labelNode.set(label || '', options?.matches, options?.title, options?.labelEscapeNewLines);
} else {
this.labelNode.textContent = label || '';
}
this.nameNode.setLabel(label, options);
if (description || this.descriptionNode) {
if (!this.descriptionNode) {
......@@ -157,3 +158,80 @@ export class IconLabel extends Disposable {
}
}
}
class Label {
private label: string | string[] | undefined = undefined;
private singleLabel: HTMLElement | undefined = undefined;
constructor(private container: HTMLElement) { }
setLabel(label: string | string[], options?: IIconLabelValueOptions): void {
if (this.label === label) {
return;
}
this.label = label;
if (typeof label === 'string') {
if (!this.singleLabel) {
this.container.innerHTML = '';
this.singleLabel = dom.append(this.container, dom.$('a.label-name'));
}
this.singleLabel.textContent = label;
} else {
this.container.innerHTML = '';
this.singleLabel = undefined;
for (let i = 0; i < label.length; i++) {
const l = label[i];
dom.append(this.container, dom.$('a.label-name', undefined, l));
if (i < label.length - 1) {
dom.append(this.container, dom.$('span.label-separator', undefined, options?.separator || '/'));
}
}
}
}
}
class LabelWithHighlights {
private label: string | string[] | undefined = undefined;
private singleLabel: HighlightedLabel | undefined = undefined;
constructor(private container: HTMLElement, private supportCodicons: boolean) { }
setLabel(label: string | string[], options?: IIconLabelValueOptions): void {
if (this.label === label) {
return;
}
this.label = label;
if (typeof label === 'string') {
if (!this.singleLabel) {
this.container.innerHTML = '';
this.singleLabel = new HighlightedLabel(dom.append(this.container, dom.$('a.label-name')), this.supportCodicons);
}
this.singleLabel.set(label, options?.matches, options?.title, options?.labelEscapeNewLines);
} else {
this.container.innerHTML = '';
this.singleLabel = undefined;
for (let i = 0; i < label.length; i++) {
const l = label[i];
const highlightedLabel = new HighlightedLabel(dom.append(this.container, dom.$('a.label-name')), this.supportCodicons);
highlightedLabel.set(l, options?.matches, options?.title, options?.labelEscapeNewLines);
if (i < label.length - 1) {
dom.append(this.container, dom.$('span.label-separator', undefined, options?.separator || '/'));
}
}
}
}
}
......@@ -31,25 +31,31 @@
flex-shrink: 0; /* fix for https://github.com/Microsoft/vscode/issues/13787 */
}
.monaco-icon-label > .monaco-icon-label-description-container {
overflow: hidden; /* this causes the label/description to shrink first if decorations are enabled */
.monaco-icon-label > .monaco-icon-label-container {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
flex: 1;
}
.monaco-icon-label > .monaco-icon-label-description-container > .label-name {
.monaco-icon-label > .monaco-icon-label-container > .monaco-icon-name-container > .label-name {
color: inherit;
white-space: pre; /* enable to show labels that include multiple whitespaces */
}
.monaco-icon-label > .monaco-icon-label-description-container > .label-description {
.monaco-icon-label > .monaco-icon-label-container > .monaco-icon-name-container > .label-separator {
margin: 0 0.2em;
}
.monaco-icon-label > .monaco-icon-label-container > .monaco-icon-description-container > .label-description {
opacity: .7;
margin-left: 0.5em;
font-size: 0.9em;
white-space: pre; /* enable to show labels that include multiple whitespaces */
}
.monaco-icon-label.italic > .monaco-icon-label-description-container > .label-name,
.monaco-icon-label.italic > .monaco-icon-label-description-container > .label-description {
.monaco-icon-label.italic > .monaco-icon-label-container > .monaco-icon-name-container > .label-name,
.monaco-icon-label.italic > .monaco-icon-description-container > .label-description {
font-style: italic;
}
......@@ -58,7 +64,6 @@
font-size: 90%;
font-weight: 600;
padding: 0 16px 0 5px;
margin-left: auto;
text-align: center;
}
......
......@@ -28,7 +28,7 @@ import { withNullAsUndefined } from 'vs/base/common/types';
export interface IResourceLabelProps {
resource?: URI;
name?: string;
name?: string | string[];
description?: string;
}
......@@ -41,6 +41,7 @@ export interface IResourceLabelOptions extends IIconLabelValueOptions {
export interface IFileLabelOptions extends IResourceLabelOptions {
hideLabel?: boolean;
hidePath?: boolean;
readonly parentCount?: number;
}
export interface IResourceLabel extends IDisposable {
......@@ -442,7 +443,8 @@ class ResourceLabelWidget extends IconLabel {
title: '',
italic: this.options && this.options.italic,
matches: this.options && this.options.matches,
extraClasses: []
extraClasses: [],
separator: this.options?.separator
};
const resource = this.label.resource;
......
......@@ -51,6 +51,7 @@ import { ITreeCompressionDelegate } from 'vs/base/browser/ui/tree/asyncDataTree'
import { ICompressibleTreeRenderer } from 'vs/base/browser/ui/tree/objectTree';
import { ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
import { VSBuffer } from 'vs/base/common/buffer';
import { ILabelService } from 'vs/platform/label/common/label';
export class ExplorerDelegate implements IListVirtualDelegate<ExplorerItem> {
......@@ -132,7 +133,8 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
@IContextViewService private readonly contextViewService: IContextViewService,
@IThemeService private readonly themeService: IThemeService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IExplorerService private readonly explorerService: IExplorerService
@IExplorerService private readonly explorerService: IExplorerService,
@ILabelService private readonly labelService: ILabelService
) {
this.config = this.configurationService.getValue<IFilesConfiguration>();
this.configListener = this.configurationService.onDidChangeConfiguration(e => {
......@@ -175,7 +177,7 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
templateData.elementDisposable.dispose();
const stat = node.element.elements[node.element.elements.length - 1];
const label = node.element.elements.map(e => e.name).join('/');
const label = node.element.elements.map(e => e.name);
const editableData = this.explorerService.getEditableData(stat);
// File Label
......@@ -191,7 +193,7 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
}
}
private renderStat(stat: ExplorerItem, label: string, filterData: FuzzyScore | undefined, templateData: IFileTemplateData): IDisposable {
private renderStat(stat: ExplorerItem, label: string | string[], filterData: FuzzyScore | undefined, templateData: IFileTemplateData): IDisposable {
templateData.label.element.style.display = 'flex';
const extraClasses = ['explorer-item'];
if (this.explorerService.isCut(stat)) {
......@@ -202,7 +204,8 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
fileKind: stat.isRoot ? FileKind.ROOT_FOLDER : stat.isDirectory ? FileKind.FOLDER : FileKind.FILE,
extraClasses,
fileDecorations: this.config.explorer.decorations,
matches: createMatches(filterData)
matches: createMatches(filterData),
separator: this.labelService.getSeparator(stat.resource.scheme, stat.resource.authority)
});
return templateData.label.onDidRender(() => {
......
......@@ -135,6 +135,7 @@
.scm-viewlet .monaco-list .monaco-list-row .resource-group > .actions,
.scm-viewlet .monaco-list .monaco-list-row .resource > .name > .monaco-icon-label > .actions {
display: none;
max-width: fit-content;
}
.scm-viewlet .monaco-list .monaco-list-row:hover .resource-group > .actions,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册