Implement notebook cell status bar item contributions

Fix #104958
This commit is contained in:
Rob Lourens
2020-08-26 17:07:10 -07:00
parent 6b90f4d6dc
commit b58f4549b2
18 changed files with 662 additions and 125 deletions
+40
View File
@@ -1613,6 +1613,35 @@ declare module 'vscode' {
resolveKernel?(kernel: T, document: NotebookDocument, webview: NotebookCommunication, token: CancellationToken): ProviderResult<void>;
}
/**
* Represents the alignment of status bar items.
*/
export enum NotebookCellStatusBarAlignment {
/**
* Aligned to the left side.
*/
Left = 1,
/**
* Aligned to the right side.
*/
Right = 2
}
export interface NotebookCellStatusBarItem {
readonly cell: NotebookCell;
readonly alignment: NotebookCellStatusBarAlignment;
readonly priority?: number;
text: string;
tooltip: string | undefined;
command: string | Command | undefined;
accessibilityInformation?: AccessibilityInformation;
show(): void;
hide(): void;
dispose(): void;
}
export namespace notebook {
export function registerNotebookContentProvider(
notebookType: string,
@@ -1670,6 +1699,17 @@ declare module 'vscode' {
export function createConcatTextDocument(notebook: NotebookDocument, selector?: DocumentSelector): NotebookConcatTextDocument;
export const onDidChangeActiveNotebookKernel: Event<{ document: NotebookDocument, kernel: NotebookKernel | undefined }>;
/**
* Creates a notebook cell status bar [item](#NotebookCellStatusBarItem).
* It will be disposed automatically when the notebook document is closed or the cell is deleted.
*
* @param cell The cell on which this item should be shown.
* @param alignment The alignment of the item.
* @param priority The priority of the item. Higher values mean the item should be shown more to the left.
* @return A new status bar item.
*/
export function createCellStatusBarItem(cell: NotebookCell, alignment?: NotebookCellStatusBarAlignment, priority?: number): NotebookCellStatusBarItem;
}
//#endregion
@@ -4,23 +4,23 @@
*--------------------------------------------------------------------------------------------*/
import * as DOM from 'vs/base/browser/dom';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IExtHostContext, ExtHostNotebookShape, ExtHostContext, INotebookDocumentsAndEditorsDelta } from '../common/extHost.protocol';
import { Disposable, IDisposable, combinedDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/common/notebookService';
import { NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, CellKind, INotebookKernelInfo, INotebookKernelInfoDto, IEditor, INotebookDocumentFilter, DisplayOrderKey, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { IRelativePattern } from 'vs/base/common/glob';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { Emitter } from 'vs/base/common/event';
import { IRelativePattern } from 'vs/base/common/glob';
import { combinedDisposable, Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { ILogService } from 'vs/platform/log/common/log';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService';
import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, CellKind, DisplayOrderKey, ICellEditOperation, IEditor, INotebookDocumentFilter, INotebookKernelInfo, INotebookKernelInfoDto, NotebookCellMetadata, NotebookCellOutputsSplice, NotebookDocumentMetadata, NOTEBOOK_DISPLAY_ORDER, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IMainNotebookController, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, INotebookCellStatusBarEntryDto, INotebookDocumentsAndEditorsDelta, MainContext, MainThreadNotebookShape, NotebookExtensionDescription } from '../common/extHost.protocol';
class DocumentAndEditorState {
static ofSets<T>(before: Set<T>, after: Set<T>): { removed: T[], added: T[] } {
@@ -137,6 +137,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
private _toDisposeOnEditorRemove = new Map<string, IDisposable>();
private _currentState?: DocumentAndEditorState;
private _editorEventListenersMapping: Map<string, DisposableStore> = new Map();
private readonly _cellStatusBarEntries: Map<number, IDisposable> = new Map();
constructor(
extHostContext: IExtHostContext,
@@ -144,8 +145,8 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
@IConfigurationService private readonly configurationService: IConfigurationService,
@IEditorService private readonly editorService: IEditorService,
@IAccessibilityService private readonly accessibilityService: IAccessibilityService,
@ILogService private readonly logService: ILogService
@ILogService private readonly logService: ILogService,
@INotebookCellStatusBarService private readonly cellStatusBarService: INotebookCellStatusBarService
) {
super();
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostNotebook);
@@ -603,6 +604,24 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
textModel?.handleUnknownChange();
}
async $setStatusBarEntry(id: number, rawStatusBarEntry: INotebookCellStatusBarEntryDto): Promise<void> {
const statusBarEntry = {
...rawStatusBarEntry,
...{ cellResource: URI.revive(rawStatusBarEntry.cellResource) }
};
const existingEntry = this._cellStatusBarEntries.get(id);
if (existingEntry) {
existingEntry.dispose();
}
if (statusBarEntry.visible) {
this._cellStatusBarEntries.set(
id,
this.cellStatusBarService.addEntry(statusBarEntry));
}
}
}
export class MainThreadNotebookKernel implements INotebookKernelInfo {
@@ -992,6 +992,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
createConcatTextDocument(notebook, selector) {
checkProposedApiEnabled(extension);
return new ExtHostNotebookConcatDocument(extHostNotebook, extHostDocuments, notebook, selector);
},
createCellStatusBarItem(cell: vscode.NotebookCell, alignment?: vscode.NotebookCellStatusBarAlignment, priority?: number): vscode.NotebookCellStatusBarItem {
checkProposedApiEnabled(extension);
return extHostNotebook.createNotebookCellStatusBarItemInternal(cell, alignment, priority);
}
};
@@ -1126,7 +1130,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
CellKind: extHostTypes.CellKind,
CellOutputKind: extHostTypes.CellOutputKind,
NotebookCellRunState: extHostTypes.NotebookCellRunState,
NotebookRunState: extHostTypes.NotebookRunState
NotebookRunState: extHostTypes.NotebookRunState,
NotebookCellStatusBarAlignment: extHostTypes.NotebookCellStatusBarAlignment
};
};
}
@@ -51,7 +51,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
import { revive } from 'vs/base/common/marshalling';
import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, INotebookKernelInfoDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, INotebookKernelInfoDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata, INotebookCellStatusBarEntry } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { Dto } from 'vs/base/common/types';
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
@@ -719,6 +719,8 @@ export type NotebookCellOutputsSplice = [
IProcessedOutput[]
];
export type INotebookCellStatusBarEntryDto = Dto<INotebookCellStatusBarEntry>;
export interface MainThreadNotebookShape extends IDisposable {
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, supportBackup: boolean, kernelInfoDto: INotebookKernelInfoDto | undefined, options: { transientOutputs: boolean; transientMetadata: TransientMetadata }): Promise<void>;
$onNotebookChange(viewType: string, resource: UriComponents): Promise<void>;
@@ -734,6 +736,7 @@ export interface MainThreadNotebookShape extends IDisposable {
$updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata | undefined): Promise<void>;
$spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[]): Promise<void>;
$postMessage(editorId: string, forRendererId: string | undefined, value: any): Promise<boolean>;
$setStatusBarEntry(id: number, statusBarEntry: INotebookCellStatusBarEntryDto): Promise<void>;
$onDidEdit(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void;
$onContentChange(resource: UriComponents, viewType: string): void;
+209 -4
View File
@@ -14,15 +14,15 @@ import { ISplice } from 'vs/base/common/sequence';
import { URI, UriComponents } from 'vs/base/common/uri';
import * as UUID from 'vs/base/common/uuid';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { CellKind, ExtHostNotebookShape, IMainContext, IModelAddedData, INotebookDocumentsAndEditorsDelta, INotebookEditorPropertiesChangeData, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice } from 'vs/workbench/api/common/extHost.protocol';
import { CellKind, ExtHostNotebookShape, ICommandDto, IMainContext, IModelAddedData, INotebookDocumentsAndEditorsDelta, INotebookEditorPropertiesChangeData, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice } from 'vs/workbench/api/common/extHost.protocol';
import { ILogService } from 'vs/platform/log/common/log';
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { CommandsConverter, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { ExtHostDocumentsAndEditors, IExtHostModelAddedData } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
import { CellEditType, CellOutputKind, diff, ICellDeleteEdit, ICellDto2, ICellEditOperation, ICellInsertEdit, IMainCellDto, INotebookDisplayOrder, INotebookEditData, INotebookKernelInfoDto2, IProcessedOutput, IRawOutput, NotebookCellMetadata, NotebookCellsChangedEvent, NotebookCellsChangeType, NotebookCellsSplice2, NotebookDataDto, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellEditType, CellOutputKind, CellStatusbarAlignment, CellUri, diff, ICellDeleteEdit, ICellDto2, ICellEditOperation, ICellInsertEdit, IMainCellDto, INotebookCellStatusBarEntry, INotebookDisplayOrder, INotebookEditData, INotebookKernelInfoDto2, IProcessedOutput, IRawOutput, NotebookCellMetadata, NotebookCellsChangedEvent, NotebookCellsChangeType, NotebookCellsSplice2, NotebookDataDto, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import * as vscode from 'vscode';
import { Cache } from './cache';
import { ResourceMap } from 'vs/base/common/map';
@@ -72,6 +72,9 @@ export class ExtHostCell extends Disposable {
};
}
private _onDidDispose = new Emitter<void>();
readonly onDidDispose: Event<void> = this._onDidDispose.event;
private _onDidChangeOutputs = new Emitter<ISplice<IProcessedOutput>[]>();
readonly onDidChangeOutputs: Event<ISplice<IProcessedOutput>[]> = this._onDidChangeOutputs.event;
@@ -134,6 +137,11 @@ export class ExtHostCell extends Disposable {
return this._cell;
}
dispose() {
super.dispose();
this._onDidDispose.fire();
}
private _updateOutputs(newOutputs: vscode.CellOutput[]) {
const rawDiffs = diff<vscode.CellOutput>(this._outputs || [], newOutputs || [], (a) => {
return this._outputMapping.has(a);
@@ -345,7 +353,9 @@ export class ExtHostNotebookDocument extends Disposable {
}
if (!this._cellDisposableMapping.has(extCell.handle)) {
this._cellDisposableMapping.set(extCell.handle, new DisposableStore());
const store = new DisposableStore();
store.add(extCell);
this._cellDisposableMapping.set(extCell.handle, store);
}
const store = this._cellDisposableMapping.get(extCell.handle)!;
@@ -880,6 +890,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
private readonly _unInitializedDocuments = new ResourceMap<ExtHostNotebookDocument>();
private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor; }>();
private readonly _webviewComm = new Map<string, ExtHostWebviewCommWrapper>();
private readonly _commandsConverter: CommandsConverter;
private readonly _onDidChangeNotebookCells = new Emitter<vscode.NotebookCellsChangeEvent>();
readonly onDidChangeNotebookCells = this._onDidChangeNotebookCells.event;
private readonly _onDidChangeCellOutputs = new Emitter<vscode.NotebookCellOutputsChangeEvent>();
@@ -928,6 +939,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
private readonly _extensionStoragePaths: IExtensionStoragePaths,
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadNotebook);
this._commandsConverter = commands.converter;
commands.registerArgumentProcessor({
// Serialized INotebookCellActionContext
@@ -1542,6 +1554,24 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
this._onDidChangeActiveNotebookEditor.fire(this._activeNotebookEditor);
}
}
createNotebookCellStatusBarItemInternal(cell: vscode.NotebookCell, alignment: extHostTypes.NotebookCellStatusBarAlignment | undefined, priority: number | undefined) {
const statusBarItem = new NotebookCellStatusBarItemInternal(this._proxy, this._commandsConverter, cell, alignment, priority);
// Look up the ExtHostCell for this NotebookCell URI, bind to its disposable lifecycle
const parsedUri = CellUri.parse(cell.uri);
if (parsedUri) {
const document = this._documents.get(parsedUri.notebook);
if (document) {
const cell = document.getCell(parsedUri.handle);
if (cell) {
Event.once(cell.onDidDispose)(() => statusBarItem.dispose());
}
}
}
return statusBarItem;
}
}
function hashPath(resource: URI): string {
@@ -1553,3 +1583,178 @@ function isEditEvent(e: vscode.NotebookDocumentEditEvent | vscode.NotebookDocume
return typeof (e as vscode.NotebookDocumentEditEvent).undo === 'function'
&& typeof (e as vscode.NotebookDocumentEditEvent).redo === 'function';
}
export class NotebookCellStatusBarItemInternal extends Disposable {
private static NEXT_ID = 0;
private readonly _id = NotebookCellStatusBarItemInternal.NEXT_ID++;
private readonly _internalCommandRegistration: DisposableStore;
private _isDisposed = false;
private _alignment: extHostTypes.NotebookCellStatusBarAlignment;
constructor(
private readonly _proxy: MainThreadNotebookShape,
private readonly _commands: CommandsConverter,
private readonly _cell: vscode.NotebookCell,
alignment: extHostTypes.NotebookCellStatusBarAlignment | undefined,
private _priority: number | undefined) {
super();
this._internalCommandRegistration = this._register(new DisposableStore());
this._alignment = alignment ?? extHostTypes.NotebookCellStatusBarAlignment.Left;
}
private _apiItem: vscode.NotebookCellStatusBarItem | undefined;
get apiItem(): vscode.NotebookCellStatusBarItem {
if (!this._apiItem) {
this._apiItem = createNotebookCellStatusBarApiItem(this);
}
return this._apiItem;
}
get cell(): vscode.NotebookCell {
return this._cell;
}
get alignment(): extHostTypes.NotebookCellStatusBarAlignment {
return this._alignment;
}
set alignment(v: extHostTypes.NotebookCellStatusBarAlignment) {
this._alignment = v;
this.update();
}
get priority(): number | undefined {
return this._priority;
}
set priority(v: number | undefined) {
this._priority = v;
this.update();
}
private _text: string = '';
get text(): string {
return this._text;
}
set text(v: string) {
this._text = v;
this.update();
}
private _tooltip: string | undefined;
get tooltip(): string | undefined {
return this._tooltip;
}
set tooltip(v: string | undefined) {
this._tooltip = v;
this.update();
}
private _command?: {
readonly fromApi: string | vscode.Command,
readonly internal: ICommandDto,
};
get command(): string | vscode.Command | undefined {
return this._command?.fromApi;
}
set command(command: string | vscode.Command | undefined) {
if (this._command?.fromApi === command) {
return;
}
this._internalCommandRegistration.clear();
if (typeof command === 'string') {
this._command = {
fromApi: command,
internal: this._commands.toInternal({ title: '', command }, this._internalCommandRegistration),
};
} else if (command) {
this._command = {
fromApi: command,
internal: this._commands.toInternal(command, this._internalCommandRegistration),
};
} else {
this._command = undefined;
}
this.update();
}
private _accessibilityInformation: vscode.AccessibilityInformation | undefined;
get accessibilityInformation(): vscode.AccessibilityInformation | undefined {
return this._accessibilityInformation;
}
set accessibilityInformation(v: vscode.AccessibilityInformation | undefined) {
this._accessibilityInformation = v;
this.update();
}
private _visible: boolean = false;
show(): void {
this._visible = true;
this.update();
}
hide(): void {
this._visible = false;
this.update();
}
dispose(): void {
this.hide();
this._isDisposed = true;
this._internalCommandRegistration.dispose();
}
private update(): void {
if (this._isDisposed) {
return;
}
const entry: INotebookCellStatusBarEntry = {
alignment: this.alignment === extHostTypes.NotebookCellStatusBarAlignment.Left ? CellStatusbarAlignment.LEFT : CellStatusbarAlignment.RIGHT,
cellResource: this.cell.uri,
command: this._command?.internal,
text: this.text,
tooltip: this.tooltip,
accessibilityInformation: this.accessibilityInformation,
priority: this.priority,
visible: this._visible
};
this._proxy.$setStatusBarEntry(this._id, entry);
}
}
function createNotebookCellStatusBarApiItem(internalItem: NotebookCellStatusBarItemInternal): vscode.NotebookCellStatusBarItem {
return Object.freeze({
cell: internalItem.cell,
get alignment() { return internalItem.alignment; },
set alignment(v: NotebookCellStatusBarItemInternal['alignment']) { internalItem.alignment = v; },
get priority() { return internalItem.priority; },
set priority(v: NotebookCellStatusBarItemInternal['priority']) { internalItem.priority = v; },
get text() { return internalItem.text; },
set text(v: NotebookCellStatusBarItemInternal['text']) { internalItem.text = v; },
get tooltip() { return internalItem.tooltip; },
set tooltip(v: NotebookCellStatusBarItemInternal['tooltip']) { internalItem.tooltip = v; },
get command() { return internalItem.command; },
set command(v: NotebookCellStatusBarItemInternal['command']) { internalItem.command = v; },
get accessibilityInformation() { return internalItem.accessibilityInformation; },
set accessibilityInformation(v: NotebookCellStatusBarItemInternal['accessibilityInformation']) { internalItem.accessibilityInformation = v; },
show() { internalItem.show(); },
hide() { internalItem.hide(); },
dispose() { internalItem.dispose(); }
});
}
@@ -2757,6 +2757,12 @@ export enum NotebookRunState {
Idle = 2
}
export enum NotebookCellStatusBarAlignment {
Left = 1,
Right = 2
}
//#endregion
//#region Timeline
@@ -362,11 +362,29 @@
.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-status-right {
padding-right: 12px;
z-index: 26;
display: flex;
}
.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-status-right .cell-contributed-items-right {
display: flex;
flex-wrap: wrap;
overflow: hidden;
}
.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-status-item {
display: flex;
align-items: center;
white-space: pre;
height: 21px; /* Editor outline is -1px in, don't overlap */
padding: 0px 6px;
}
.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-status-item.cell-status-item-has-command {
cursor: pointer;
}
.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-language-picker {
height: 21px; /* Editor outline is -1px in, don't overlap */
padding: 0px 6px;
cursor: pointer;
}
@@ -380,6 +398,10 @@
align-items: center;
}
.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-status-message {
margin-right: 6px;
}
.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-run-status {
height: 100%;
display: flex;
@@ -46,6 +46,8 @@ import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/n
import { NotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor';
import { INotebookEditorWorkerService } from 'vs/workbench/contrib/notebook/common/services/notebookWorkerService';
import { NotebookEditorWorkerServiceImpl } from 'vs/workbench/contrib/notebook/common/services/notebookWorkerServiceImpl';
import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService';
import { NotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/browser/notebookCellStatusBarServiceImpl';
// Editor Contribution
@@ -445,6 +447,7 @@ workbenchContributionsRegistry.registerWorkbenchContribution(CellContentProvider
registerSingleton(INotebookService, NotebookService);
registerSingleton(INotebookEditorWorkerService, NotebookEditorWorkerServiceImpl);
registerSingleton(INotebookEditorModelResolverService, NotebookModelResolverService, true);
registerSingleton(INotebookCellStatusBarService, NotebookCellStatusBarService, true);
const configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
configurationRegistry.registerConfiguration({
@@ -27,10 +27,10 @@ import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { IMenu } from 'vs/platform/actions/common/actions';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { CellLanguageStatusBarItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/commonViewComponents';
import { EditorOptions } from 'vs/workbench/common/editor';
import { IResourceEditorInput } from 'vs/platform/editor/common/editor';
import { IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation';
import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets';
export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey<boolean>('notebookFindWidgetFocused', false);
@@ -525,8 +525,7 @@ export interface BaseCellRenderTemplate {
elementDisposables: DisposableStore;
bottomCellContainer: HTMLElement;
currentRenderedCell?: ICellViewModel;
statusBarContainer: HTMLElement;
languageStatusBarItem: CellLanguageStatusBarItem;
statusBar: CellEditorStatusBar;
titleMenu: IMenu;
toJSON: () => object;
}
@@ -539,7 +538,6 @@ export interface MarkdownCellRenderTemplate extends BaseCellRenderTemplate {
export interface CodeCellRenderTemplate extends BaseCellRenderTemplate {
cellRunState: RunStateRenderer;
cellStatusMessageContainer: HTMLElement;
runToolbar: ToolBar;
runButtonContainer: HTMLElement;
executionOrderLabel: HTMLElement;
@@ -0,0 +1,54 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { ResourceMap } from 'vs/base/common/map';
import { URI } from 'vs/base/common/uri';
import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService';
import { INotebookCellStatusBarEntry } from 'vs/workbench/contrib/notebook/common/notebookCommon';
export class NotebookCellStatusBarService extends Disposable implements INotebookCellStatusBarService {
private _onDidChangeEntriesForCell = new Emitter<URI>();
readonly onDidChangeEntriesForCell: Event<URI> = this._onDidChangeEntriesForCell.event;
private _entries = new ResourceMap<Set<INotebookCellStatusBarEntry>>();
private removeEntry(entry: INotebookCellStatusBarEntry) {
const existingEntries = this._entries.get(entry.cellResource);
if (existingEntries) {
existingEntries.delete(entry);
if (!existingEntries.size) {
this._entries.delete(entry.cellResource);
}
}
this._onDidChangeEntriesForCell.fire(entry.cellResource);
}
addEntry(entry: INotebookCellStatusBarEntry): IDisposable {
const existingEntries = this._entries.get(entry.cellResource) ?? new Set();
existingEntries.add(entry);
this._entries.set(entry.cellResource, existingEntries);
this._onDidChangeEntriesForCell.fire(entry.cellResource);
return {
dispose: () => {
this.removeEntry(entry);
}
};
}
getEntries(cell: URI): INotebookCellStatusBarEntry[] {
const existingEntries = this._entries.get(cell);
return existingEntries ?
Array.from(existingEntries.values()) :
[];
}
readonly _serviceBrand: undefined;
}
@@ -1928,7 +1928,8 @@ registerThemingParticipant((theme, collector) => {
const cellStatusBarHoverBg = theme.getColor(cellStatusBarItemHover);
if (cellStatusBarHoverBg) {
collector.addRule(`.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-language-picker:hover { background-color: ${cellStatusBarHoverBg}; }`);
collector.addRule(`.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-language-picker:hover,
.monaco-workbench .notebookOverlay .cell-statusbar-container .cell-status-item.cell-status-item-has-command:hover { background-color: ${cellStatusBarHoverBg}; }`);
}
const cellInsertionIndicatorColor = theme.getColor(cellInsertionIndicator);
@@ -40,15 +40,16 @@ import { CancelCellAction, DeleteCellAction, ExecuteCellAction, INotebookCellAct
import { BaseCellRenderTemplate, CellEditState, CodeCellRenderTemplate, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, isCodeCellRenderTemplate, MarkdownCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellContextKeyManager } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellContextKeys';
import { CellMenus } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellMenus';
import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets';
import { CodeCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/codeCell';
import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/commonViewComponents';
import { CellDragAndDropController, DRAGGING_CLASS } from 'vs/workbench/contrib/notebook/browser/view/renderers/dnd';
import { StatefulMarkdownCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/markdownCell';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { CellKind, NotebookCellMetadata, NotebookCellRunState, ShowCellStatusbarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { createAndFillInActionBarActionsWithVerticalSeparators, VerticalSeparator, VerticalSeparatorViewItem } from './cellActionView';
import { CodiconActionViewItem, CellLanguageStatusBarItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/commonViewComponents';
import { CellDragAndDropController, DRAGGING_CLASS } from 'vs/workbench/contrib/notebook/browser/view/renderers/dnd';
const $ = DOM.$;
@@ -403,7 +404,7 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
const bottomCellContainer = DOM.append(container, $('.cell-bottom-toolbar-container'));
const betweenCellToolbar = disposables.add(this.createBetweenCellToolbar(bottomCellContainer, disposables, contextKeyService));
const statusBar = this.instantiationService.createInstance(CellEditorStatusBar, editorPart);
const statusBar = disposables.add(this.instantiationService.createInstance(CellEditorStatusBar, editorPart));
const titleMenu = disposables.add(this.cellMenus.getCellTitleMenu(contextKeyService));
const templateData: MarkdownCellRenderTemplate = {
@@ -422,9 +423,8 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
deleteToolbar,
betweenCellToolbar,
bottomCellContainer,
statusBarContainer: statusBar.statusBarContainer,
languageStatusBarItem: statusBar.languageStatusBarItem,
titleMenu,
statusBar,
toJSON: () => { return {}; }
};
this.dndController.registerDragHandle(templateData, rootContainer, container, () => this.getDragImage(templateData));
@@ -493,7 +493,7 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
elementDisposables.add(this.editorOptions.onDidChange(newValue => markdownCell.updateEditorOptions(newValue)));
elementDisposables.add(markdownCell);
templateData.languageStatusBarItem.update(element, this.notebookEditor);
templateData.statusBar.update(toolbarContext);
}
disposeTemplate(templateData: MarkdownCellRenderTemplate): void {
@@ -605,27 +605,6 @@ class CodeCellDragImageRenderer {
}
}
class CellEditorStatusBar {
readonly cellStatusMessageContainer: HTMLElement;
readonly cellRunStatusContainer: HTMLElement;
readonly statusBarContainer: HTMLElement;
readonly languageStatusBarItem: CellLanguageStatusBarItem;
readonly durationContainer: HTMLElement;
constructor(
container: HTMLElement,
@IInstantiationService instantiationService: IInstantiationService
) {
this.statusBarContainer = DOM.append(container, $('.cell-statusbar-container'));
const leftStatusBarItems = DOM.append(this.statusBarContainer, $('.cell-status-left'));
const rightStatusBarItems = DOM.append(this.statusBarContainer, $('.cell-status-right'));
this.cellRunStatusContainer = DOM.append(leftStatusBarItems, $('.cell-run-status'));
this.durationContainer = DOM.append(leftStatusBarItems, $('.cell-run-duration'));
this.cellStatusMessageContainer = DOM.append(leftStatusBarItems, $('.cell-status-message'));
this.languageStatusBarItem = instantiationService.createInstance(CellLanguageStatusBarItem, rightStatusBarItems);
}
}
export class CodeCellRenderer extends AbstractCellRenderer implements IListRenderer<CodeCellViewModel, CodeCellRenderTemplate> {
static readonly TEMPLATE_ID = 'code_cell';
@@ -692,7 +671,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
progressBar.hide();
disposables.add(progressBar);
const statusBar = this.instantiationService.createInstance(CellEditorStatusBar, editorPart);
const statusBar = disposables.add(this.instantiationService.createInstance(CellEditorStatusBar, editorPart));
const timer = new TimerRenderer(statusBar.durationContainer);
const cellRunState = new RunStateRenderer(statusBar.cellRunStatusContainer, runToolbar, this.instantiationService);
@@ -715,11 +694,9 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
contextKeyService,
container,
cellContainer,
statusBarContainer: statusBar.statusBarContainer,
cellRunState,
cellStatusMessageContainer: statusBar.cellStatusMessageContainer,
languageStatusBarItem: statusBar.languageStatusBarItem,
progressBar,
statusBar,
focusIndicatorLeft: focusIndicator,
focusIndicatorRight,
focusIndicatorBottom,
@@ -766,7 +743,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
const metadata = element.getEvaluatedMetadata(this.notebookEditor.viewModel!.notebookDocument.metadata);
DOM.toggleClass(templateData.container, 'runnable', !!metadata.runnable);
this.updateExecutionOrder(metadata, templateData);
templateData.cellStatusMessageContainer.textContent = metadata?.statusMessage || '';
templateData.statusBar.cellStatusMessageContainer.textContent = metadata?.statusMessage || '';
templateData.cellRunState.renderState(element.metadata?.runState);
@@ -880,7 +857,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
this.setBetweenCellToolbarContext(templateData, element, toolbarContext);
templateData.languageStatusBarItem.update(element, this.notebookEditor);
templateData.statusBar.update(toolbarContext);
}
disposeTemplate(templateData: CodeCellRenderTemplate): void {
@@ -0,0 +1,217 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as DOM from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel';
import { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions';
import { stripCodicons } from 'vs/base/common/codicons';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { KeyCode } from 'vs/base/common/keyCodes';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { extUri } from 'vs/base/common/resources';
import { IModeService } from 'vs/editor/common/services/modeService';
import { localize } from 'vs/nls';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { ChangeCellLanguageAction, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
import { ICellViewModel, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService';
import { CellKind, CellStatusbarAlignment, INotebookCellStatusBarEntry } from 'vs/workbench/contrib/notebook/common/notebookCommon';
const $ = DOM.$;
export class CellEditorStatusBar extends Disposable {
readonly cellStatusMessageContainer: HTMLElement;
readonly cellRunStatusContainer: HTMLElement;
readonly statusBarContainer: HTMLElement;
readonly languageStatusBarItem: CellLanguageStatusBarItem;
readonly durationContainer: HTMLElement;
private readonly leftContributedItemsContainer: HTMLElement;
private readonly rightContributedItemsContainer: HTMLElement;
private readonly itemsDisposable: DisposableStore;
private currentContext: INotebookCellActionContext | undefined;
constructor(
container: HTMLElement,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@INotebookCellStatusBarService private readonly notebookCellStatusBarService: INotebookCellStatusBarService
) {
super();
this.statusBarContainer = DOM.append(container, $('.cell-statusbar-container'));
const leftItemsContainer = DOM.append(this.statusBarContainer, $('.cell-status-left'));
const rightItemsContainer = DOM.append(this.statusBarContainer, $('.cell-status-right'));
this.cellRunStatusContainer = DOM.append(leftItemsContainer, $('.cell-run-status'));
this.durationContainer = DOM.append(leftItemsContainer, $('.cell-run-duration'));
this.cellStatusMessageContainer = DOM.append(leftItemsContainer, $('.cell-status-message'));
this.leftContributedItemsContainer = DOM.append(leftItemsContainer, $('.cell-contributed-items-left'));
this.rightContributedItemsContainer = DOM.append(rightItemsContainer, $('.cell-contributed-items-right'));
this.languageStatusBarItem = instantiationService.createInstance(CellLanguageStatusBarItem, rightItemsContainer);
this.itemsDisposable = this._register(new DisposableStore());
this._register(this.notebookCellStatusBarService.onDidChangeEntriesForCell(e => {
if (this.currentContext && extUri.isEqual(e, this.currentContext.cell.uri)) {
this.updateStatusBarItems();
}
}));
}
update(context: INotebookCellActionContext) {
this.currentContext = context;
this.languageStatusBarItem.update(context.cell, context.notebookEditor);
this.updateStatusBarItems();
}
layout(width: number): void {
this.statusBarContainer.style.width = `${width}px`;
}
private updateStatusBarItems() {
if (!this.currentContext) {
return;
}
this.leftContributedItemsContainer.innerHTML = '';
this.rightContributedItemsContainer.innerHTML = '';
this.itemsDisposable.clear();
const items = this.notebookCellStatusBarService.getEntries(this.currentContext.cell.uri);
items.sort((itemA, itemB) => {
return (itemB.priority ?? 0) - (itemA.priority ?? 0);
});
items.forEach(item => {
const itemView = this.itemsDisposable.add(this.instantiationService.createInstance(CellStatusBarItem, this.currentContext!, item));
if (item.alignment === CellStatusbarAlignment.LEFT) {
this.leftContributedItemsContainer.appendChild(itemView.container);
} else {
this.rightContributedItemsContainer.appendChild(itemView.container);
}
});
}
}
class CellStatusBarItem extends Disposable {
readonly container = $('.cell-status-item');
constructor(
private readonly _context: INotebookCellActionContext,
private readonly _itemModel: INotebookCellStatusBarEntry,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@ICommandService private readonly commandService: ICommandService,
@INotificationService private readonly notificationService: INotificationService
) {
super();
new CodiconLabel(this.container).text = this._itemModel.text;
let ariaLabel: string;
let role: string | undefined;
if (this._itemModel.accessibilityInformation) {
ariaLabel = this._itemModel.accessibilityInformation.label;
role = this._itemModel.accessibilityInformation.role;
} else {
ariaLabel = this._itemModel.text ? stripCodicons(this._itemModel.text).trim() : '';
}
if (ariaLabel) {
this.container.setAttribute('aria-label', ariaLabel);
}
if (role) {
this.container.setAttribute('role', role);
}
this.container.title = this._itemModel.tooltip ?? '';
if (this._itemModel.command) {
this.container.classList.add('cell-status-item-has-command');
this.container.tabIndex = 0;
this._register(DOM.addDisposableListener(this.container, DOM.EventType.CLICK, _e => {
this.executeCommand();
}));
this._register(DOM.addDisposableListener(this.container, DOM.EventType.KEY_UP, e => {
const event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Space) || event.equals(KeyCode.Enter)) {
this.executeCommand();
}
}));
}
}
private async executeCommand(): Promise<void> {
const command = this._itemModel.command;
if (!command) {
return;
}
const id = typeof command === 'string' ? command : command.id;
const args = typeof command === 'string' ? [] : command.arguments ?? [];
args.unshift(this._context);
this.telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', { id, from: 'cell status bar' });
try {
await this.commandService.executeCommand(id, ...args);
} catch (error) {
this.notificationService.error(toErrorMessage(error));
}
}
}
export class CellLanguageStatusBarItem extends Disposable {
private readonly labelElement: HTMLElement;
private cell: ICellViewModel | undefined;
private editor: INotebookEditor | undefined;
private cellDisposables: DisposableStore;
constructor(
readonly container: HTMLElement,
@IModeService private readonly modeService: IModeService,
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
super();
this.labelElement = DOM.append(container, $('.cell-language-picker.cell-status-item'));
this.labelElement.tabIndex = 0;
this._register(DOM.addDisposableListener(this.labelElement, DOM.EventType.CLICK, () => {
this.run();
}));
this._register(DOM.addDisposableListener(this.labelElement, DOM.EventType.KEY_UP, e => {
const event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Space) || event.equals(KeyCode.Enter)) {
this.run();
}
}));
this._register(this.cellDisposables = new DisposableStore());
}
private run() {
this.instantiationService.invokeFunction(accessor => {
new ChangeCellLanguageAction().run(accessor, { notebookEditor: this.editor!, cell: this.cell! });
});
}
update(cell: ICellViewModel, editor: INotebookEditor): void {
this.cellDisposables.clear();
this.cell = cell;
this.editor = editor;
this.render();
this.cellDisposables.add(this.cell.model.onDidChangeLanguage(() => this.render()));
}
private render(): void {
const modeId = this.cell?.cellKind === CellKind.Markdown ? 'markdown' : this.modeService.getModeIdForLanguageName(this.cell!.language) || this.cell!.language;
this.labelElement.textContent = this.modeService.getLanguageName(modeId) || this.modeService.getLanguageName('plaintext');
this.labelElement.title = localize('notebook.cell.status.language', "Select Cell Language Mode");
}
}
@@ -401,7 +401,7 @@ export class CodeCell extends Disposable {
private layoutEditor(dimension: IDimension): void {
this.templateData.editor?.layout(dimension);
this.templateData.statusBarContainer.style.width = `${dimension.width}px`;
this.templateData.statusBar.layout(dimension.width);
}
private onCellWidthChange(): void {
@@ -3,22 +3,12 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import * as DOM from 'vs/base/browser/dom';
import { renderCodicons } from 'vs/base/common/codicons';
import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { MenuItemAction } from 'vs/platform/actions/common/actions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { renderCodicons } from 'vs/base/common/codicons';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { ICellViewModel, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ChangeCellLanguageAction } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
const $ = DOM.$;
export class CodiconActionViewItem extends MenuEntryActionViewItem {
constructor(
@@ -35,45 +25,3 @@ export class CodiconActionViewItem extends MenuEntryActionViewItem {
}
}
}
export class CellLanguageStatusBarItem extends Disposable {
private readonly labelElement: HTMLElement;
private cell: ICellViewModel | undefined;
private editor: INotebookEditor | undefined;
private cellDisposables: DisposableStore;
constructor(
readonly container: HTMLElement,
@IModeService private readonly modeService: IModeService,
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
super();
this.labelElement = DOM.append(container, $('.cell-language-picker'));
this.labelElement.tabIndex = 0;
this._register(DOM.addDisposableListener(this.labelElement, DOM.EventType.CLICK, () => {
this.instantiationService.invokeFunction(accessor => {
new ChangeCellLanguageAction().run(accessor, { notebookEditor: this.editor!, cell: this.cell! });
});
}));
this._register(this.cellDisposables = new DisposableStore());
}
update(cell: ICellViewModel, editor: INotebookEditor): void {
this.cellDisposables.clear();
this.cell = cell;
this.editor = editor;
this.render();
this.cellDisposables.add(this.cell.model.onDidChangeLanguage(() => this.render()));
}
private render(): void {
const modeId = this.cell?.cellKind === CellKind.Markdown ? 'markdown' : this.modeService.getModeIdForLanguageName(this.cell!.language) || this.cell!.language;
this.labelElement.textContent = this.modeService.getLanguageName(modeId) || this.modeService.getLanguageName('plaintext');
this.labelElement.title = localize('notebook.cell.status.language', "Select Cell Language Mode");
}
}
@@ -282,7 +282,7 @@ export class StatefulMarkdownCell extends Disposable {
private layoutEditor(dimension: DOM.IDimension): void {
this.editor?.layout(dimension);
this.templateData.statusBarContainer.style.width = `${dimension.width}px`;
this.templateData.statusBar.layout(dimension.width);
}
private onCellEditorWidthChange(): void {
@@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { INotebookCellStatusBarEntry } from 'vs/workbench/contrib/notebook/common/notebookCommon';
export const INotebookCellStatusBarService = createDecorator<INotebookCellStatusBarService>('notebookCellStatusBarService');
export interface INotebookCellStatusBarService {
readonly _serviceBrand: undefined;
onDidChangeEntriesForCell: Event<URI>;
addEntry(entry: INotebookCellStatusBarEntry): IDisposable;
getEntries(cell: URI): INotebookCellStatusBarEntry[];
}
@@ -3,22 +3,24 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CancellationToken } from 'vs/base/common/cancellation';
import { IDiffResult, ISequence } from 'vs/base/common/diff/diff';
import { Event } from 'vs/base/common/event';
import * as glob from 'vs/base/common/glob';
import { IDisposable } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
import { basename } from 'vs/base/common/path';
import { isWindows } from 'vs/base/common/platform';
import { ISplice } from 'vs/base/common/sequence';
import { URI, UriComponents } from 'vs/base/common/uri';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { Command } from 'vs/editor/common/modes';
import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IEditorModel } from 'vs/platform/editor/common/editor';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Schemas } from 'vs/base/common/network';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IRevertOptions } from 'vs/workbench/common/editor';
import { basename } from 'vs/base/common/path';
import { IDiffResult, ISequence } from 'vs/base/common/diff/diff';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
export enum CellKind {
Markdown = 1,
@@ -744,7 +746,6 @@ export interface INotebookKernelProvider {
cancelNotebook(uri: URI, kernelId: string, handle: number | undefined): Promise<void>;
}
export class CellSequence implements ISequence {
constructor(readonly textModel: NotebookTextModel) {
@@ -764,6 +765,23 @@ export interface INotebookDiffResult {
cellsDiff: IDiffResult,
linesDiff?: { originalCellhandle: number, modifiedCellhandle: number, lineChanges: editorCommon.ILineChange[] }[];
}
export interface INotebookCellStatusBarEntry {
readonly cellResource: URI;
readonly alignment: CellStatusbarAlignment;
readonly priority?: number;
readonly text: string;
readonly tooltip: string | undefined;
readonly command: string | Command | undefined;
readonly accessibilityInformation?: IAccessibilityInformation;
readonly visible: boolean;
}
export const DisplayOrderKey = 'notebook.displayOrder';
export const CellToolbarLocKey = 'notebook.cellToolbarLocation';
export const ShowCellStatusbarKey = 'notebook.showCellStatusbar';
export const enum CellStatusbarAlignment {
LEFT,
RIGHT
}