mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
use task icon/color in quick pick (#151990)
This commit is contained in:
parent
9e2b6e082c
commit
33b1980f6f
|
@ -79,7 +79,7 @@ import { IViewsService, IViewDescriptorService } from 'vs/workbench/common/views
|
|||
import { isWorkspaceFolder, ITaskQuickPickEntry, QUICKOPEN_DETAIL_CONFIG, TaskQuickPick, QUICKOPEN_SKIP_CONFIG, configureTaskIcon } from 'vs/workbench/contrib/tasks/browser/taskQuickPick';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { once } from 'vs/base/common/functional';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { IWorkspaceTrustManagementService, IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { VirtualWorkspaceContext } from 'vs/workbench/common/contextkeys';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
@ -94,7 +94,7 @@ export namespace ConfigureTaskAction {
|
|||
export const TEXT = nls.localize('ConfigureTaskRunnerAction.label', "Configure Task");
|
||||
}
|
||||
|
||||
type TaskQuickPickEntryType = (IQuickPickItem & { task: Task }) | (IQuickPickItem & { folder: IWorkspaceFolder }) | (IQuickPickItem & { settingType: string });
|
||||
export type TaskQuickPickEntryType = (IQuickPickItem & { task: Task }) | (IQuickPickItem & { folder: IWorkspaceFolder }) | (IQuickPickItem & { settingType: string });
|
||||
|
||||
class ProblemReporter implements TaskConfig.IProblemReporter {
|
||||
|
||||
|
@ -256,7 +256,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
|
|||
@IViewDescriptorService private readonly _viewDescriptorService: IViewDescriptorService,
|
||||
@IWorkspaceTrustRequestService private readonly _workspaceTrustRequestService: IWorkspaceTrustRequestService,
|
||||
@IWorkspaceTrustManagementService private readonly _workspaceTrustManagementService: IWorkspaceTrustManagementService,
|
||||
@ILogService private readonly _logService: ILogService
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@IThemeService private readonly _themeService: IThemeService
|
||||
) {
|
||||
super();
|
||||
|
||||
|
@ -2519,7 +2520,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
|
|||
}
|
||||
|
||||
private async _showTwoLevelQuickPick(placeHolder: string, defaultEntry?: ITaskQuickPickEntry) {
|
||||
return TaskQuickPick.show(this, this._configurationService, this._quickInputService, this._notificationService, this._dialogService, placeHolder, defaultEntry);
|
||||
return TaskQuickPick.show(this, this._configurationService, this._quickInputService, this._notificationService, this._dialogService, this._themeService, placeHolder, defaultEntry);
|
||||
}
|
||||
|
||||
private async _showQuickPick(tasks: Promise<Task[]> | Task[], placeHolder: string, defaultEntry?: ITaskQuickPickEntry, group: boolean = false, sort: boolean = false, selectedEntry?: ITaskQuickPickEntry, additionalEntries?: ITaskQuickPickEntry[]): Promise<ITaskQuickPickEntry | undefined | null> {
|
||||
|
@ -3143,7 +3144,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
|
|||
if (this._isTaskEntry(selection)) {
|
||||
this._configureTask(selection.task);
|
||||
} else if (this._isSettingEntry(selection)) {
|
||||
const taskQuickPick = new TaskQuickPick(this, this._configurationService, this._quickInputService, this._notificationService, this._dialogService);
|
||||
const taskQuickPick = new TaskQuickPick(this, this._configurationService, this._quickInputService, this._notificationService, this._themeService, this._dialogService);
|
||||
taskQuickPick.handleSettingOption(selection.settingType);
|
||||
} else if (selection.folder && (this._contextService.getWorkbenchState() !== WorkbenchState.EMPTY)) {
|
||||
this._openTaskFile(selection.folder.toResource('.vscode/tasks.json'), TaskSourceKind.Workspace);
|
||||
|
@ -3201,7 +3202,9 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
|
|||
if (tasks.length > 0) {
|
||||
tasks = tasks.sort((a, b) => a._label.localeCompare(b._label));
|
||||
for (const task of tasks) {
|
||||
entries.push({ label: task._label, task, description: this.getTaskDescription(task), detail: this._showDetail() ? task.configurationProperties.detail : undefined });
|
||||
const entry = { label: TaskQuickPick.getTaskLabelWithIcon(task), task, description: this.getTaskDescription(task), detail: this._showDetail() ? task.configurationProperties.detail : undefined };
|
||||
TaskQuickPick.applyColorStyles(task, entry, this._themeService);
|
||||
entries.push(entry);
|
||||
if (!ContributedTask.is(task)) {
|
||||
configuredCount++;
|
||||
}
|
||||
|
|
|
@ -9,16 +9,18 @@ import { Task, ContributedTask, CustomTask, ConfiguringTask, TaskSorter, KeyedTa
|
|||
import { IWorkspace, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import * as Types from 'vs/base/common/types';
|
||||
import { ITaskService, IWorkspaceFolderTaskResult } from 'vs/workbench/contrib/tasks/common/taskService';
|
||||
import { IQuickPickItem, QuickPickInput, IQuickPick, IQuickInputButton } from 'vs/base/parts/quickinput/common/quickInput';
|
||||
import { IQuickPickItem, QuickPickInput, IQuickPick, IQuickInputButton, IQuickPickSeparator } from 'vs/base/parts/quickinput/common/quickInput';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { getColorClass, getColorStyleElement, getStandardColors } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
|
||||
import { TaskQuickPickEntryType } from 'vs/workbench/contrib/tasks/browser/abstractTaskService';
|
||||
|
||||
export const QUICKOPEN_DETAIL_CONFIG = 'task.quickOpen.detail';
|
||||
export const QUICKOPEN_SKIP_CONFIG = 'task.quickOpen.skip';
|
||||
|
@ -49,6 +51,7 @@ export class TaskQuickPick extends Disposable {
|
|||
private _configurationService: IConfigurationService,
|
||||
private _quickInputService: IQuickInputService,
|
||||
private _notificationService: INotificationService,
|
||||
private _themeService: IThemeService,
|
||||
private _dialogService: IDialogService) {
|
||||
super();
|
||||
this._sorter = this._taskService.createSorter();
|
||||
|
@ -61,7 +64,7 @@ export class TaskQuickPick extends Disposable {
|
|||
|
||||
private _guessTaskLabel(task: Task | ConfiguringTask): string {
|
||||
if (task._label) {
|
||||
return task._label;
|
||||
return TaskQuickPick.getTaskLabelWithIcon(task);
|
||||
}
|
||||
if (ConfiguringTask.is(task)) {
|
||||
let label: string = task.configures.type;
|
||||
|
@ -74,9 +77,29 @@ export class TaskQuickPick extends Disposable {
|
|||
return '';
|
||||
}
|
||||
|
||||
public static getTaskLabelWithIcon(task: Task | ConfiguringTask): string {
|
||||
return task.configurationProperties.icon ? `$(${task.configurationProperties.icon}) ${task._label}` : task.configurationProperties.color ? `$(${Codicon.tools.id}) ${task._label}` : `${task._label}`;
|
||||
}
|
||||
|
||||
public static applyColorStyles(task: Task | ConfiguringTask, entry: TaskQuickPickEntryType | ITaskTwoLevelQuickPickEntry, themeService: IThemeService): void {
|
||||
if (task.configurationProperties.color) {
|
||||
const colorTheme = themeService.getColorTheme();
|
||||
const styleElement = getColorStyleElement(colorTheme);
|
||||
entry.iconClasses = [getColorClass(task.configurationProperties.color)];
|
||||
document.body.appendChild(styleElement);
|
||||
}
|
||||
}
|
||||
|
||||
private _createTaskEntry(task: Task | ConfiguringTask, extraButtons: IQuickInputButton[] = []): ITaskTwoLevelQuickPickEntry {
|
||||
const customizeIconButton = { iconClass: ThemeIcon.asClassName(Codicon.pencil), tooltip: nls.localize('setIconAndColor', "Choose color and icon") };
|
||||
const entry: ITaskTwoLevelQuickPickEntry = { label: this._guessTaskLabel(task), description: this._taskService.getTaskDescription(task), task, detail: this._showDetail() ? task.configurationProperties.detail : undefined };
|
||||
entry.buttons = [{ iconClass: ThemeIcon.asClassName(configureTaskIcon), tooltip: nls.localize('configureTask', "Configure Task") }, ...extraButtons];
|
||||
entry.buttons = [];
|
||||
if (CustomTask.is(task)) {
|
||||
entry.buttons.push(customizeIconButton);
|
||||
}
|
||||
entry.buttons.push({ iconClass: ThemeIcon.asClassName(configureTaskIcon), tooltip: nls.localize('configureTask', "Configure Task") });
|
||||
entry.buttons.push(...extraButtons);
|
||||
TaskQuickPick.applyColorStyles(task, entry, this._themeService);
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -211,6 +234,9 @@ export class TaskQuickPick extends Disposable {
|
|||
if (indexToRemove >= 0) {
|
||||
picker.items = [...picker.items.slice(0, indexToRemove), ...picker.items.slice(indexToRemove + 1)];
|
||||
}
|
||||
} else if (context.button.iconClass = ThemeIcon.asClassName(Codicon.pencil)) {
|
||||
await this._setColor(task);
|
||||
await this._setIcon(task);
|
||||
} else {
|
||||
this._quickInputService.cancel();
|
||||
if (ContributedTask.is(task)) {
|
||||
|
@ -265,6 +291,74 @@ export class TaskQuickPick extends Disposable {
|
|||
return;
|
||||
}
|
||||
|
||||
private async _setColor(task: Task | ConfiguringTask | null | string | undefined): Promise<void> {
|
||||
if (task === undefined || task === null || typeof task === 'string') {
|
||||
return;
|
||||
}
|
||||
const colorTheme = this._themeService.getColorTheme();
|
||||
const standardColors: string[] = getStandardColors(colorTheme);
|
||||
const styleElement = getColorStyleElement(colorTheme);
|
||||
const items: (IQuickPickItem | IQuickPickSeparator)[] = [];
|
||||
for (const colorKey of standardColors) {
|
||||
const colorClass = getColorClass(colorKey);
|
||||
items.push({
|
||||
label: `$(${Codicon.circleFilled.id}) ${colorKey.replace('terminal.ansi', '')}`, id: colorKey, description: colorKey, iconClasses: [colorClass]
|
||||
});
|
||||
}
|
||||
items.push({ type: 'separator' });
|
||||
const showAllColorsItem = { label: 'Reset to default' };
|
||||
items.push(showAllColorsItem);
|
||||
document.body.appendChild(styleElement);
|
||||
|
||||
const quickPick = this._quickInputService.createQuickPick();
|
||||
quickPick.items = items;
|
||||
quickPick.matchOnDescription = true;
|
||||
quickPick.show();
|
||||
const disposables: IDisposable[] = [];
|
||||
const result = await new Promise<IQuickPickItem | undefined>(r => {
|
||||
disposables.push(quickPick.onDidHide(() => r(undefined)));
|
||||
disposables.push(quickPick.onDidAccept(() => r(quickPick.selectedItems[0])));
|
||||
});
|
||||
dispose(disposables);
|
||||
|
||||
if (result && task && typeof task !== 'string') {
|
||||
task.configurationProperties.color = result.id;
|
||||
}
|
||||
document.body.removeChild(styleElement);
|
||||
quickPick.hide();
|
||||
}
|
||||
|
||||
private async _setIcon(task: Task | ConfiguringTask | null | string | undefined): Promise<void> {
|
||||
if (task === undefined || task === null || typeof task === 'string') {
|
||||
return;
|
||||
}
|
||||
type Item = IQuickPickItem & { icon: ThemeIcon };
|
||||
const items: Item[] = [];
|
||||
for (const icon of Codicon.getAll()) {
|
||||
items.push({ label: `$(${icon.id})`, description: `${icon.id}`, id: icon.id, icon, iconClasses: task.configurationProperties.color ? [getColorClass(task.configurationProperties.color)] : undefined });
|
||||
}
|
||||
|
||||
const quickPick = this._quickInputService.createQuickPick();
|
||||
quickPick.items = items;
|
||||
quickPick.matchOnDescription = true;
|
||||
quickPick.show();
|
||||
const disposables: IDisposable[] = [];
|
||||
const result = await new Promise<IQuickPickItem | undefined>(r => {
|
||||
disposables.push(quickPick.onDidHide(() => r(undefined)));
|
||||
disposables.push(quickPick.onDidAccept(() => r(quickPick.selectedItems[0])));
|
||||
});
|
||||
dispose(disposables);
|
||||
|
||||
if (result && task && typeof task !== 'string') {
|
||||
task.configurationProperties.icon = result.id;
|
||||
}
|
||||
if (CustomTask.is(task) && result) {
|
||||
await this._taskService.customize(task, { icon: result.id, color: task.configurationProperties.color }, false);
|
||||
}
|
||||
quickPick.hide();
|
||||
}
|
||||
|
||||
|
||||
private async _doPickerFirstLevel(picker: IQuickPick<ITaskTwoLevelQuickPickEntry>, taskQuickPickEntries: QuickPickInput<ITaskTwoLevelQuickPickEntry>[]): Promise<Task | ConfiguringTask | string | null | undefined> {
|
||||
picker.items = taskQuickPickEntries;
|
||||
const firstLevelPickerResult = await new Promise<ITaskTwoLevelQuickPickEntry | undefined | null>(resolve => {
|
||||
|
@ -367,8 +461,8 @@ export class TaskQuickPick extends Disposable {
|
|||
|
||||
static async show(taskService: ITaskService, configurationService: IConfigurationService,
|
||||
quickInputService: IQuickInputService, notificationService: INotificationService,
|
||||
dialogService: IDialogService, placeHolder: string, defaultEntry?: ITaskQuickPickEntry) {
|
||||
const taskQuickPick = new TaskQuickPick(taskService, configurationService, quickInputService, notificationService, dialogService);
|
||||
dialogService: IDialogService, themeService: IThemeService, placeHolder: string, defaultEntry?: ITaskQuickPickEntry) {
|
||||
const taskQuickPick = new TaskQuickPick(taskService, configurationService, quickInputService, notificationService, themeService, dialogService);
|
||||
return taskQuickPick.show(placeHolder, defaultEntry);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
|||
import { isString } from 'vs/base/common/types';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQuickAccessItem> {
|
||||
|
||||
|
@ -28,7 +29,8 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQ
|
|||
@IConfigurationService private _configurationService: IConfigurationService,
|
||||
@IQuickInputService private _quickInputService: IQuickInputService,
|
||||
@INotificationService private _notificationService: INotificationService,
|
||||
@IDialogService private _dialogService: IDialogService
|
||||
@IDialogService private _dialogService: IDialogService,
|
||||
@IThemeService private _themeService: IThemeService
|
||||
) {
|
||||
super(TasksQuickAccessProvider.PREFIX, {
|
||||
noResultsPick: {
|
||||
|
@ -42,7 +44,7 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQ
|
|||
return [];
|
||||
}
|
||||
|
||||
const taskQuickPick = new TaskQuickPick(this._taskService, this._configurationService, this._quickInputService, this._notificationService, this._dialogService);
|
||||
const taskQuickPick = new TaskQuickPick(this._taskService, this._configurationService, this._quickInputService, this._notificationService, this._themeService, this._dialogService);
|
||||
const topLevelPicks = await taskQuickPick.getTopLevelEntries();
|
||||
const taskPicks: Array<IPickerQuickAccessItem | IQuickPickSeparator> = [];
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ export interface ICustomizationProperties {
|
|||
group?: string | { kind?: string; isDefault?: boolean };
|
||||
problemMatcher?: string | string[];
|
||||
isBackground?: boolean;
|
||||
color?: string;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface ITaskFilter {
|
||||
|
|
|
@ -43,6 +43,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile
|
|||
import { IWorkspaceTrustManagementService, IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
interface IWorkspaceFolderConfigurationResult {
|
||||
workspaceFolder: IWorkspaceFolder;
|
||||
|
@ -83,7 +84,8 @@ export class TaskService extends AbstractTaskService {
|
|||
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
|
||||
@IWorkspaceTrustRequestService workspaceTrustRequestService: IWorkspaceTrustRequestService,
|
||||
@IWorkspaceTrustManagementService workspaceTrustManagementService: IWorkspaceTrustManagementService,
|
||||
@ILogService logService: ILogService) {
|
||||
@ILogService logService: ILogService,
|
||||
@IThemeService themeService: IThemeService) {
|
||||
super(configurationService,
|
||||
markerService,
|
||||
outputService,
|
||||
|
@ -115,7 +117,8 @@ export class TaskService extends AbstractTaskService {
|
|||
viewDescriptorService,
|
||||
workspaceTrustRequestService,
|
||||
workspaceTrustManagementService,
|
||||
logService);
|
||||
logService,
|
||||
themeService);
|
||||
this._register(lifecycleService.onBeforeShutdown(event => event.veto(this.beforeShutdown(), 'veto.tasks')));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue