Skip to content

Commit 0473fff

Browse files
committed
render icon for metadata
1 parent 017aef6 commit 0473fff

5 files changed

Lines changed: 71 additions & 6 deletions

File tree

src/vs/editor/common/modes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,7 @@ export interface WorkspaceEditMetadata {
12651265
needsConfirmation: boolean;
12661266
label: string;
12671267
description?: string;
1268+
icon?: { id: string } | { light: URI, dark: URI };
12681269
}
12691270

12701271
export interface WorkspaceFileEditOptions {

src/vs/monaco.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5901,6 +5901,12 @@ declare namespace monaco.languages {
59015901
needsConfirmation: boolean;
59025902
label: string;
59035903
description?: string;
5904+
icon?: {
5905+
id: string;
5906+
} | {
5907+
light: Uri;
5908+
dark: Uri;
5909+
};
59045910
}
59055911

59065912
export interface WorkspaceFileEditOptions {

src/vs/workbench/contrib/bulkEdit/browser/bulkEdit.css

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,30 @@
4141
font-size: 0.9em;
4242
white-space: pre
4343
}
44+
45+
.monaco-workbench .bulk-edit-panel .monaco-tl-contents.category {
46+
display: flex;
47+
flex: 1;
48+
flex-flow: row nowrap;
49+
align-items: center;
50+
}
51+
52+
.monaco-workbench .bulk-edit-panel .monaco-tl-contents.category .theme-icon {
53+
margin-right: 4px;
54+
}
55+
56+
.monaco-workbench .bulk-edit-panel .monaco-tl-contents.category .uri-icon {
57+
background-repeat: no-repeat;
58+
background-image: var(--background-light);
59+
background-position: left center;
60+
background-size: contain;
61+
margin-right: 4px;
62+
height: 100%;
63+
width: 16px;
64+
}
65+
66+
.vs-dark .monaco-workbench .bulk-edit-panel .monaco-tl-contents.category .uri-icon,
67+
.hc-black .monaco-workbench .bulk-edit-panel .monaco-tl-contents.category .uri-icon
68+
{
69+
background-image: var(--background-dark);
70+
}

src/vs/workbench/contrib/bulkEdit/browser/bulkEditPreview.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { Emitter, Event } from 'vs/base/common/event';
1919
import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
2020
import { ConflictDetector } from 'vs/workbench/services/bulkEdit/browser/conflicts';
2121
import { values } from 'vs/base/common/map';
22+
import { localize } from 'vs/nls';
2223

2324
export class CheckedObject {
2425

@@ -84,13 +85,19 @@ export class BulkFileOperation extends CheckedObject {
8485

8586
export class BulkCategory {
8687

87-
static keyOf(metadata: WorkspaceEditMetadata | undefined) {
88+
private static readonly _defaultMetadata = Object.freeze({
89+
label: localize('default', "Other"),
90+
icon: { id: 'codicon/symbol-file' },
91+
needsConfirmation: false
92+
});
93+
94+
static keyOf(metadata?: WorkspaceEditMetadata) {
8895
return metadata?.label || '<default>';
8996
}
9097

9198
readonly operationByResource = new Map<string, BulkFileOperation>();
9299

93-
constructor(readonly label: string | undefined) { }
100+
constructor(readonly metadata: WorkspaceEditMetadata = BulkCategory._defaultMetadata) { }
94101

95102
get fileOperations(): BulkFileOperation[] {
96103
return values(this.operationByResource);
@@ -194,7 +201,7 @@ export class BulkFileOperations {
194201
let key = BulkCategory.keyOf(edit.metadata);
195202
let category = operationByCategory.get(key);
196203
if (!category) {
197-
category = new BulkCategory(edit.metadata?.label);
204+
category = new BulkCategory(edit.metadata);
198205
operationByCategory.set(key, category);
199206
}
200207
insert(category.operationByResource);

src/vs/workbench/contrib/bulkEdit/browser/bulkEditTree.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import type { IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'
2323
import type { IAriaProvider } from 'vs/base/browser/ui/list/listView';
2424
import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel';
2525
import { basename } from 'vs/base/common/resources';
26+
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
2627

2728
// --- VIEW MODEL
2829

@@ -201,7 +202,7 @@ export class BulkEditIdentityProvider implements IIdentityProvider<BulkEditEleme
201202
} else if (element instanceof TextEditElement) {
202203
return element.parent.uri.toString() + JSON.stringify(element.edit.textEdit);
203204
} else {
204-
return element.label || '<default>';
205+
return JSON.stringify(element.metadata);
205206
}
206207
}
207208
}
@@ -225,9 +226,13 @@ export class BulkEditAriaProvider implements IAriaProvider<BulkEditElement> {
225226

226227
class CategoryElementTemplate {
227228

229+
readonly icon: HTMLDivElement;
228230
readonly label: IconLabel;
229231

230232
constructor(container: HTMLElement) {
233+
container.classList.add('category');
234+
this.icon = document.createElement('div');
235+
container.appendChild(this.icon);
231236
this.label = new IconLabel(container);
232237
}
233238
}
@@ -243,7 +248,26 @@ export class CategoryElementRenderer implements ITreeRenderer<BulkCategory, Fuzz
243248
}
244249

245250
renderElement(node: ITreeNode<BulkCategory, FuzzyScore>, _index: number, template: CategoryElementTemplate): void {
246-
template.label.setLabel(node.element.label || localize('default', "Other"));
251+
252+
template.icon.style.setProperty('--background-dark', null);
253+
template.icon.style.setProperty('--background-light', null);
254+
255+
const { metadata } = node.element;
256+
if (ThemeIcon.isThemeIcon(metadata.icon)) {
257+
// css
258+
const className = ThemeIcon.asClassName(metadata.icon);
259+
template.icon.className = className ? `theme-icon ${className}` : '';
260+
261+
} else if (metadata.icon) {
262+
// background-image
263+
template.icon.className = 'uri-icon';
264+
template.icon.style.setProperty('--background-dark', `url("${metadata.icon.dark.toString(true)}")`);
265+
template.icon.style.setProperty('--background-light', `url("${metadata.icon.light.toString(true)}")`);
266+
}
267+
268+
template.label.setLabel(metadata.label, metadata.description, {
269+
descriptionMatches: createMatches(node.filterData),
270+
});
247271
}
248272

249273
disposeTemplate(template: CategoryElementTemplate): void {
@@ -431,7 +455,7 @@ export class BulkEditNaviLabelProvider implements IKeyboardNavigationLabelProvid
431455
if (element instanceof FileElement) {
432456
return basename(element.uri);
433457
} else if (element instanceof BulkCategory) {
434-
return element.label;
458+
return element.metadata.label;
435459
}
436460
return undefined;
437461
}

0 commit comments

Comments
 (0)