Path: blob/main/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelView.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { ActionViewItem, IActionViewItemOptions } from '../../../../../base/browser/ui/actionbar/actionViewItems.js';6import { Action, IAction } from '../../../../../base/common/actions.js';7import { Event } from '../../../../../base/common/event.js';8import { localize, localize2 } from '../../../../../nls.js';9import { Action2, MenuId, registerAction2 } from '../../../../../platform/actions/common/actions.js';10import { ContextKeyExpr, IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js';11import { ExtensionIdentifier } from '../../../../../platform/extensions/common/extensions.js';12import { IInstantiationService, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';13import { ThemeIcon } from '../../../../../base/common/themables.js';14import { NOTEBOOK_ACTIONS_CATEGORY, SELECT_KERNEL_ID } from '../controller/coreActions.js';15import { getNotebookEditorFromEditorPane, INotebookEditor } from '../notebookBrowser.js';16import { selectKernelIcon } from '../notebookIcons.js';17import { KernelPickerMRUStrategy, KernelQuickPickContext } from './notebookKernelQuickPickStrategy.js';18import { NotebookTextModel } from '../../common/model/notebookTextModel.js';19import { NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT } from '../../common/notebookContextKeys.js';20import { INotebookKernel, INotebookKernelHistoryService, INotebookKernelService } from '../../common/notebookKernelService.js';21import { IEditorService } from '../../../../services/editor/common/editorService.js';2223function getEditorFromContext(editorService: IEditorService, context?: KernelQuickPickContext): INotebookEditor | undefined {24let editor: INotebookEditor | undefined;25if (context !== undefined && 'notebookEditorId' in context) {26const editorId = context.notebookEditorId;27const matchingEditor = editorService.visibleEditorPanes.find((editorPane) => {28const notebookEditor = getNotebookEditorFromEditorPane(editorPane);29return notebookEditor?.getId() === editorId;30});31editor = getNotebookEditorFromEditorPane(matchingEditor);32} else if (context !== undefined && 'notebookEditor' in context) {33editor = context?.notebookEditor;34} else {35editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);36}3738return editor;39}4041function shouldSkip(42selected: INotebookKernel | undefined,43controllerId: string | undefined,44extensionId: string | undefined,45context: KernelQuickPickContext | undefined): boolean {4647return !!(selected && (48(context && 'skipIfAlreadySelected' in context && context.skipIfAlreadySelected) ||49// target kernel is already selected50(controllerId && selected.id === controllerId && ExtensionIdentifier.equals(selected.extension, extensionId))51));52}5354registerAction2(class extends Action2 {55constructor() {56super({57id: SELECT_KERNEL_ID,58category: NOTEBOOK_ACTIONS_CATEGORY,59title: localize2('notebookActions.selectKernel', 'Select Notebook Kernel'),60icon: selectKernelIcon,61f1: true,62precondition: NOTEBOOK_IS_ACTIVE_EDITOR,63menu: [{64id: MenuId.EditorTitle,65when: ContextKeyExpr.and(66NOTEBOOK_IS_ACTIVE_EDITOR,67ContextKeyExpr.notEquals('config.notebook.globalToolbar', true)68),69group: 'navigation',70order: -1071}, {72id: MenuId.NotebookToolbar,73when: ContextKeyExpr.equals('config.notebook.globalToolbar', true),74group: 'status',75order: -1076}, {77id: MenuId.InteractiveToolbar,78when: NOTEBOOK_KERNEL_COUNT.notEqualsTo(0),79group: 'status',80order: -1081}],82metadata: {83description: localize('notebookActions.selectKernel.args', "Notebook Kernel Args"),84args: [85{86name: 'kernelInfo',87description: 'The kernel info',88schema: {89'type': 'object',90'required': ['id', 'extension'],91'properties': {92'id': {93'type': 'string'94},95'extension': {96'type': 'string'97},98'notebookEditorId': {99'type': 'string'100}101}102}103}104]105},106});107}108109async run(accessor: ServicesAccessor, context?: KernelQuickPickContext): Promise<boolean> {110const instantiationService = accessor.get(IInstantiationService);111const editorService = accessor.get(IEditorService);112113const editor = getEditorFromContext(editorService, context);114115if (!editor || !editor.hasModel()) {116return false;117}118119let controllerId = context && 'id' in context ? context.id : undefined;120let extensionId = context && 'extension' in context ? context.extension : undefined;121122if (controllerId && (typeof controllerId !== 'string' || typeof extensionId !== 'string')) {123// validate context: id & extension MUST be strings124controllerId = undefined;125extensionId = undefined;126}127128const notebook = editor.textModel;129const notebookKernelService = accessor.get(INotebookKernelService);130const { selected } = notebookKernelService.getMatchingKernel(notebook);131132if (shouldSkip(selected, controllerId, extensionId, context)) {133return true;134}135136const wantedKernelId = controllerId ? `${extensionId}/${controllerId}` : undefined;137const strategy = instantiationService.createInstance(KernelPickerMRUStrategy);138return strategy.showQuickPick(editor, wantedKernelId);139}140});141142export class NotebooKernelActionViewItem extends ActionViewItem {143144private _kernelLabel?: HTMLAnchorElement;145146constructor(147actualAction: IAction,148private readonly _editor: { onDidChangeModel: Event<void>; textModel: NotebookTextModel | undefined; scopedContextKeyService?: IContextKeyService } | INotebookEditor,149options: IActionViewItemOptions,150@INotebookKernelService private readonly _notebookKernelService: INotebookKernelService,151@INotebookKernelHistoryService private readonly _notebookKernelHistoryService: INotebookKernelHistoryService,152) {153const action = new Action('fakeAction', undefined, ThemeIcon.asClassName(selectKernelIcon), true, (event) => actualAction.run(event));154super(155undefined,156action,157{ ...options, label: false, icon: true }158);159this._register(action);160this._register(_editor.onDidChangeModel(this._update, this));161this._register(_notebookKernelService.onDidAddKernel(this._update, this));162this._register(_notebookKernelService.onDidRemoveKernel(this._update, this));163this._register(_notebookKernelService.onDidChangeNotebookAffinity(this._update, this));164this._register(_notebookKernelService.onDidChangeSelectedNotebooks(this._update, this));165this._register(_notebookKernelService.onDidChangeSourceActions(this._update, this));166this._register(_notebookKernelService.onDidChangeKernelDetectionTasks(this._update, this));167}168169override render(container: HTMLElement): void {170this._update();171super.render(container);172container.classList.add('kernel-action-view-item');173this._kernelLabel = document.createElement('a');174container.appendChild(this._kernelLabel);175this.updateLabel();176}177178protected override updateLabel() {179if (this._kernelLabel) {180this._kernelLabel.classList.add('kernel-label');181this._kernelLabel.innerText = this._action.label;182}183}184185protected _update(): void {186const notebook = this._editor.textModel;187188if (!notebook) {189this._resetAction();190return;191}192193KernelPickerMRUStrategy.updateKernelStatusAction(notebook, this._action, this._notebookKernelService, this._notebookKernelHistoryService);194195this.updateClass();196}197198private _resetAction(): void {199this._action.enabled = false;200this._action.label = '';201this._action.class = '';202}203}204205206