mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 09:08:48 +01:00
nb decoration api first cut.
This commit is contained in:
Vendored
+18
@@ -1414,6 +1414,9 @@ declare module 'vscode' {
|
||||
|
||||
export interface NotebookCellRange {
|
||||
readonly start: number;
|
||||
/**
|
||||
* exclusive
|
||||
*/
|
||||
readonly end: number;
|
||||
}
|
||||
|
||||
@@ -1505,6 +1508,8 @@ declare module 'vscode' {
|
||||
*/
|
||||
edit(callback: (editBuilder: NotebookEditorEdit) => void): Thenable<boolean>;
|
||||
|
||||
setDecorations(decorationType: NotebookEditorDecorationType, range: NotebookCellRange): void;
|
||||
|
||||
revealRange(range: NotebookCellRange, revealType?: NotebookEditorRevealType): void;
|
||||
}
|
||||
|
||||
@@ -1760,6 +1765,18 @@ declare module 'vscode' {
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
export interface NotebookDecorationRenderOptions {
|
||||
backgroundColor?: string | ThemeColor;
|
||||
borderColor?: string | ThemeColor;
|
||||
top: ThemableDecorationAttachmentRenderOptions;
|
||||
}
|
||||
|
||||
export interface NotebookEditorDecorationType {
|
||||
readonly key: string;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
|
||||
export namespace notebook {
|
||||
export function registerNotebookContentProvider(
|
||||
notebookType: string,
|
||||
@@ -1783,6 +1800,7 @@ declare module 'vscode' {
|
||||
provider: NotebookKernelProvider
|
||||
): Disposable;
|
||||
|
||||
export function createNotebookEditorDecorationType(options: NotebookDecorationRenderOptions): NotebookEditorDecorationType;
|
||||
export const onDidOpenNotebookDocument: Event<NotebookDocument>;
|
||||
export const onDidCloseNotebookDocument: Event<NotebookDocument>;
|
||||
export const onDidSaveNotebookDocument: Event<NotebookDocument>;
|
||||
|
||||
@@ -18,7 +18,7 @@ import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookB
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
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, DisplayOrderKey, ICellEditOperation, ICellRange, IEditor, IMainCellDto, INotebookDocumentFilter, NotebookCellOutputsSplice, NotebookCellsChangeType, NOTEBOOK_DISPLAY_ORDER, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, DisplayOrderKey, ICellEditOperation, ICellRange, IEditor, IMainCellDto, INotebookDecorationRenderOptions, INotebookDocumentFilter, NotebookCellOutputsSplice, NotebookCellsChangeType, 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 { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
@@ -648,6 +648,22 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
}
|
||||
}
|
||||
|
||||
$registerNotebookEditorDecorationType(key: string, options: INotebookDecorationRenderOptions) {
|
||||
this._notebookService.registerEditorDecorationType(key, options);
|
||||
}
|
||||
|
||||
$removeNotebookEditorDecorationType(key: string) {
|
||||
this._notebookService.removeEditorDecorationType(key);
|
||||
}
|
||||
|
||||
$trySetDecorations(id: string, range: ICellRange, key: string) {
|
||||
const editor = this._notebookService.listNotebookEditors().find(editor => editor.getId() === id);
|
||||
if (editor && editor.isNotebookEditor) {
|
||||
const notebookEditor = editor as INotebookEditor;
|
||||
notebookEditor.setEditorDecorations(key, range);
|
||||
}
|
||||
}
|
||||
|
||||
async $setStatusBarEntry(id: number, rawStatusBarEntry: INotebookCellStatusBarEntryDto): Promise<void> {
|
||||
const statusBarEntry = {
|
||||
...rawStatusBarEntry,
|
||||
|
||||
@@ -966,6 +966,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.registerNotebookKernelProvider(extension, selector, provider);
|
||||
},
|
||||
createNotebookEditorDecorationType(options: vscode.NotebookDecorationRenderOptions): vscode.NotebookEditorDecorationType {
|
||||
return extHostNotebook.createNotebookEditorDecorationType(options);
|
||||
},
|
||||
get activeNotebookEditor(): vscode.NotebookEditor | undefined {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.activeNotebookEditor;
|
||||
|
||||
@@ -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, NotebookCellsChangedEventDto, NotebookDataDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata, INotebookCellStatusBarEntry, ICellRange } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEventDto, NotebookDataDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata, INotebookCellStatusBarEntry, ICellRange, INotebookDecorationRenderOptions } 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';
|
||||
@@ -746,6 +746,9 @@ export interface MainThreadNotebookShape extends IDisposable {
|
||||
$postMessage(editorId: string, forRendererId: string | undefined, value: any): Promise<boolean>;
|
||||
$setStatusBarEntry(id: number, statusBarEntry: INotebookCellStatusBarEntryDto): Promise<void>;
|
||||
$tryRevealRange(id: string, range: ICellRange, revealType: NotebookEditorRevealType): Promise<void>;
|
||||
$registerNotebookEditorDecorationType(key: string, options: INotebookDecorationRenderOptions): void;
|
||||
$removeNotebookEditorDecorationType(key: string): void;
|
||||
$trySetDecorations(id: string, range: ICellRange, decorationKey: string): void;
|
||||
$onUndoableContentChange(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void;
|
||||
$onContentChange(resource: UriComponents, viewType: string): void;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import * as vscode from 'vscode';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { ExtHostCell, ExtHostNotebookDocument } from './extHostNotebookDocument';
|
||||
import { ExtHostNotebookEditor } from './extHostNotebookEditor';
|
||||
import { IdGenerator } from 'vs/base/common/idGenerator';
|
||||
|
||||
class ExtHostWebviewCommWrapper extends Disposable {
|
||||
private readonly _onDidReceiveDocumentMessage = new Emitter<any>();
|
||||
@@ -187,6 +188,24 @@ async function withToken(cb: (token: CancellationToken) => any) {
|
||||
}
|
||||
}
|
||||
|
||||
export class NotebookEditorDecorationType implements vscode.NotebookEditorDecorationType {
|
||||
|
||||
private static readonly _Keys = new IdGenerator('NotebookEditorDecorationType');
|
||||
|
||||
private _proxy: MainThreadNotebookShape;
|
||||
public key: string;
|
||||
|
||||
constructor(proxy: MainThreadNotebookShape, options: vscode.NotebookDecorationRenderOptions) {
|
||||
this.key = NotebookEditorDecorationType._Keys.nextId();
|
||||
this._proxy = proxy;
|
||||
this._proxy.$registerNotebookEditorDecorationType(this.key, typeConverters.NotebookDecorationRenderOptions.from(options));
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._proxy.$removeNotebookEditorDecorationType(this.key);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostNotebookOutputRenderingHandler {
|
||||
private static _notebookKernelProviderHandlePool: number = 0;
|
||||
|
||||
@@ -338,6 +357,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
});
|
||||
}
|
||||
|
||||
createNotebookEditorDecorationType(options: vscode.NotebookDecorationRenderOptions): vscode.NotebookEditorDecorationType {
|
||||
return new NotebookEditorDecorationType(this._proxy, options);
|
||||
}
|
||||
|
||||
private _withAdapter<T>(handle: number, uri: UriComponents, callback: (adapter: ExtHostNotebookKernelProviderAdapter, document: ExtHostNotebookDocument) => Promise<T>) {
|
||||
const document = this._documents.get(URI.revive(uri));
|
||||
|
||||
|
||||
@@ -99,6 +99,8 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
readonly onDidDispose: Event<void> = this._onDidDispose.event;
|
||||
readonly onDidReceiveMessage: vscode.Event<any> = this._onDidReceiveMessage.event;
|
||||
|
||||
private _hasDecorationsForKey: { [key: string]: boolean; } = Object.create(null);
|
||||
|
||||
constructor(
|
||||
readonly id: string,
|
||||
private readonly _viewType: string,
|
||||
@@ -214,6 +216,25 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
return this._proxy.$tryApplyEdits(this._viewType, this.document.uri, editData.documentVersionId, compressedEdits);
|
||||
}
|
||||
|
||||
setDecorations(decorationType: vscode.NotebookEditorDecorationType, range: vscode.NotebookCellRange): void {
|
||||
const willBeEmpty = (range.start === range.end);
|
||||
if (willBeEmpty && !this._hasDecorationsForKey[decorationType.key]) {
|
||||
// avoid no-op call to the renderer
|
||||
return;
|
||||
}
|
||||
if (willBeEmpty) {
|
||||
delete this._hasDecorationsForKey[decorationType.key];
|
||||
} else {
|
||||
this._hasDecorationsForKey[decorationType.key] = true;
|
||||
}
|
||||
|
||||
return this._proxy.$trySetDecorations(
|
||||
this.id,
|
||||
range,
|
||||
decorationType.key
|
||||
);
|
||||
}
|
||||
|
||||
revealRange(range: vscode.NotebookCellRange, revealType?: extHostTypes.NotebookEditorRevealType) {
|
||||
this._proxy.$tryRevealRange(this.id, range, revealType || extHostTypes.NotebookEditorRevealType.Default);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import { coalesce, isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
|
||||
import { CommandsConverter } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { INotebookDecorationRenderOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
|
||||
export interface PositionLike {
|
||||
line: number;
|
||||
@@ -1348,3 +1349,13 @@ export namespace NotebookExclusiveDocumentPattern {
|
||||
return rp && typeof rp.base === 'string' && typeof rp.pattern === 'string';
|
||||
}
|
||||
}
|
||||
|
||||
export namespace NotebookDecorationRenderOptions {
|
||||
export function from(options: vscode.NotebookDecorationRenderOptions): INotebookDecorationRenderOptions {
|
||||
return {
|
||||
backgroundColor: <string | types.ThemeColor>options.backgroundColor,
|
||||
borderColor: <string | types.ThemeColor>options.borderColor,
|
||||
top: options.top ? ThemableDecorationAttachmentRenderOptions.from(options.top) : undefined
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,6 +438,9 @@ export interface INotebookEditor extends IEditor {
|
||||
*/
|
||||
changeModelDecorations<T>(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T): T | null;
|
||||
|
||||
setEditorDecorations(key: string, range: ICellRange): void;
|
||||
removeEditorDecorations(key: string): void;
|
||||
|
||||
/**
|
||||
* An event emitted on a "mouseup".
|
||||
* @event
|
||||
@@ -515,6 +518,7 @@ export interface INotebookCellList {
|
||||
}
|
||||
|
||||
export interface BaseCellRenderTemplate {
|
||||
rootContainer: HTMLElement;
|
||||
editorPart: HTMLElement;
|
||||
collapsedPart: HTMLElement;
|
||||
expandButton: HTMLElement;
|
||||
|
||||
@@ -22,7 +22,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { IEditor } from 'vs/editor/common/editorCommon';
|
||||
import { IEditor, isThemeColor } from 'vs/editor/common/editorCommon';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -34,7 +34,7 @@ import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { contrastBorder, diffInserted, diffRemoved, editorBackground, errorForeground, focusBorder, foreground, listFocusBackground, listInactiveSelectionBackground, registerColor, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, textBlockQuoteBackground, textBlockQuoteBorder, textLinkActiveForeground, textLinkForeground, textPreformatForeground, transparent } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { IColorTheme, IThemeService, registerThemingParticipant, ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
import { EditorMemento } from 'vs/workbench/browser/parts/editor/editorPane';
|
||||
import { IEditorMemento } from 'vs/workbench/common/editor';
|
||||
import { Memento, MementoObject } from 'vs/workbench/common/memento';
|
||||
@@ -54,7 +54,7 @@ import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewMod
|
||||
import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
|
||||
import { CellViewModel, IModelDecorationsChangeAccessor, INotebookEditorViewState, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { CellKind, CellToolbarLocKey, ICellRange, IInsetRenderOutput, INotebookKernelInfo2, IProcessedOutput, isTransformedDisplayOutput, NotebookCellRunState, NotebookRunState, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellKind, CellToolbarLocKey, ICellRange, IInsetRenderOutput, INotebookDecorationRenderOptions, INotebookKernelInfo2, IProcessedOutput, isTransformedDisplayOutput, NotebookCellRunState, NotebookRunState, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
|
||||
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator';
|
||||
@@ -241,7 +241,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
@ILayoutService private readonly layoutService: ILayoutService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IThemeService private readonly themeService: IThemeService
|
||||
) {
|
||||
super();
|
||||
this.isEmbedded = creationOptions.isEmbedded || false;
|
||||
@@ -1224,6 +1225,63 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
return this._list!.setHiddenAreas(_ranges, true);
|
||||
}
|
||||
|
||||
private _editorStyleSheets = new Map<string, RefCountedStyleSheet>();
|
||||
private _decorationRules = new Map<string, DecorationCSSRules>();
|
||||
private _decortionKeyToIds = new Map<string, string[]>();
|
||||
|
||||
_removeEditorStyleSheets(key: string): void {
|
||||
this._editorStyleSheets.delete(key);
|
||||
}
|
||||
|
||||
private _registerDecorationType(key: string) {
|
||||
const options = this.notebookService.resolveEditorDecorationOptions(key);
|
||||
|
||||
if (options) {
|
||||
const styleElement = DOM.createStyleSheet(this._body);
|
||||
const styleSheet = new RefCountedStyleSheet(this, key, styleElement);
|
||||
this._editorStyleSheets.set(key, styleSheet);
|
||||
this._decorationRules.set(key, new DecorationCSSRules(this.themeService, styleSheet, {
|
||||
key,
|
||||
options,
|
||||
styleSheet
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
setEditorDecorations(key: string, range: ICellRange): void {
|
||||
if (!this.viewModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
// create css style for the decoration
|
||||
if (!this._editorStyleSheets.has(key)) {
|
||||
this._registerDecorationType(key);
|
||||
}
|
||||
|
||||
const decorationRule = this._decorationRules.get(key);
|
||||
if (!decorationRule) {
|
||||
return;
|
||||
}
|
||||
|
||||
const existingDecorations = this._decortionKeyToIds.get(key) || [];
|
||||
const newDecorations = this.viewModel.viewCells.slice(range.start, range.end).map(cell => ({
|
||||
handle: cell.handle,
|
||||
options: { className: decorationRule.className, outputClassName: decorationRule.className }
|
||||
}));
|
||||
|
||||
this._decortionKeyToIds.set(key, this.deltaCellDecorations(existingDecorations, newDecorations));
|
||||
}
|
||||
|
||||
|
||||
removeEditorDecorations(key: string): void {
|
||||
if (this._decorationRules.has(key)) {
|
||||
this._decorationRules.get(key)?.dispose();
|
||||
}
|
||||
|
||||
const cellDecorations = this._decortionKeyToIds.get(key);
|
||||
this.deltaCellDecorations(cellDecorations || [], []);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Mouse Events
|
||||
@@ -1952,8 +2010,8 @@ registerThemingParticipant((theme, collector) => {
|
||||
|
||||
const cellSymbolHighlightColor = theme.getColor(cellSymbolHighlight);
|
||||
if (cellSymbolHighlightColor) {
|
||||
collector.addRule(`.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row .nb-symbolHighlight .cell-focus-indicator,
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row .nb-symbolHighlight {
|
||||
collector.addRule(`.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.nb-symbolHighlight .cell-focus-indicator,
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row.nb-symbolHighlight {
|
||||
background-color: ${cellSymbolHighlightColor} !important;
|
||||
}`);
|
||||
}
|
||||
@@ -2021,11 +2079,11 @@ registerThemingParticipant((theme, collector) => {
|
||||
const modifiedBackground = theme.getColor(editorGutterModifiedBackground);
|
||||
if (modifiedBackground) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row .nb-cell-modified .cell-focus-indicator {
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.nb-cell-modified .cell-focus-indicator {
|
||||
background-color: ${modifiedBackground} !important;
|
||||
}
|
||||
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row .nb-cell-modified {
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row.nb-cell-modified {
|
||||
background-color: ${modifiedBackground} !important;
|
||||
}`);
|
||||
}
|
||||
@@ -2033,22 +2091,22 @@ registerThemingParticipant((theme, collector) => {
|
||||
const addedBackground = theme.getColor(diffInserted);
|
||||
if (addedBackground) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row .nb-cell-added .cell-focus-indicator {
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.nb-cell-added .cell-focus-indicator {
|
||||
background-color: ${addedBackground} !important;
|
||||
}
|
||||
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row .nb-cell-added {
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row.nb-cell-added {
|
||||
background-color: ${addedBackground} !important;
|
||||
}`);
|
||||
}
|
||||
const deletedBackground = theme.getColor(diffRemoved);
|
||||
if (deletedBackground) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row .nb-cell-deleted .cell-focus-indicator {
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.nb-cell-deleted .cell-focus-indicator {
|
||||
background-color: ${deletedBackground} !important;
|
||||
}
|
||||
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row .nb-cell-deleted {
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row.nb-cell-deleted {
|
||||
background-color: ${deletedBackground} !important;
|
||||
}`);
|
||||
}
|
||||
@@ -2077,3 +2135,117 @@ registerThemingParticipant((theme, collector) => {
|
||||
|
||||
collector.addRule(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container { height: ${BOTTOM_CELL_TOOLBAR_HEIGHT}px }`);
|
||||
});
|
||||
|
||||
|
||||
export class RefCountedStyleSheet {
|
||||
private readonly _widget: NotebookEditorWidget;
|
||||
private readonly _key: string;
|
||||
private readonly _styleSheet: HTMLStyleElement;
|
||||
private _refCount: number;
|
||||
|
||||
constructor(widget: NotebookEditorWidget, key: string, styleSheet: HTMLStyleElement) {
|
||||
this._widget = widget;
|
||||
this._key = key;
|
||||
this._styleSheet = styleSheet;
|
||||
this._refCount = 0;
|
||||
}
|
||||
|
||||
public ref(): void {
|
||||
this._refCount++;
|
||||
}
|
||||
|
||||
public unref(): void {
|
||||
this._refCount--;
|
||||
if (this._refCount === 0) {
|
||||
this._styleSheet.parentNode?.removeChild(this._styleSheet);
|
||||
this._widget._removeEditorStyleSheets(this._key);
|
||||
}
|
||||
}
|
||||
|
||||
public insertRule(rule: string, index?: number): void {
|
||||
const sheet = <CSSStyleSheet>this._styleSheet.sheet;
|
||||
sheet.insertRule(rule, index);
|
||||
}
|
||||
}
|
||||
|
||||
interface ProviderArguments {
|
||||
styleSheet: RefCountedStyleSheet;
|
||||
key: string;
|
||||
options: INotebookDecorationRenderOptions;
|
||||
}
|
||||
|
||||
class DecorationCSSRules {
|
||||
private _theme: IColorTheme;
|
||||
private _className: string;
|
||||
|
||||
get className() {
|
||||
return this._className;
|
||||
}
|
||||
constructor(
|
||||
private readonly _themeService: IThemeService,
|
||||
private readonly _styleSheet: RefCountedStyleSheet,
|
||||
private readonly _providerArgs: ProviderArguments
|
||||
) {
|
||||
this._styleSheet.ref();
|
||||
this._theme = this._themeService.getColorTheme();
|
||||
this._className = CSSNameHelper.getClassName(this._providerArgs.key, CellDecorationCSSRuleType.ClassName);
|
||||
this._buildCSS();
|
||||
}
|
||||
|
||||
private _buildCSS() {
|
||||
this._styleSheet.insertRule('.foo { color: red; }', 0);
|
||||
|
||||
if (this._providerArgs.options.backgroundColor) {
|
||||
const backgroundColor = this._resolveValue(this._providerArgs.options.backgroundColor);
|
||||
this._styleSheet.insertRule(`.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.${this.className} .cell-focus-indicator,
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row.${this.className} {
|
||||
background-color: ${backgroundColor} !important;
|
||||
}`);
|
||||
}
|
||||
|
||||
if (this._providerArgs.options.borderColor) {
|
||||
const borderColor = this._resolveValue(this._providerArgs.options.borderColor);
|
||||
|
||||
this._styleSheet.insertRule(`.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.${this.className} .cell-focus-indicator-top:before,
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.${this.className} .cell-focus-indicator-bottom:before,
|
||||
.monaco-workbench .notebookOverlay .monaco-list .${this.className}.markdown-cell-row.focused:before,
|
||||
.monaco-workbench .notebookOverlay .monaco-list .${this.className}.markdown-cell-row.focused:after {
|
||||
border-color: ${borderColor} !important;
|
||||
}`);
|
||||
|
||||
// more specific rule for `.focused` can override existing rules
|
||||
this._styleSheet.insertRule(`.monaco-workbench .notebookOverlay .monaco-list:focus-within .monaco-list-row.focused.${this.className} .cell-focus-indicator-top:before,
|
||||
.monaco-workbench .notebookOverlay .monaco-list:focus-within .monaco-list-row.focused.${this.className} .cell-focus-indicator-bottom:before,
|
||||
.monaco-workbench .notebookOverlay .monaco-list:focus-within .markdown-cell-row.focused.${this.className}:before,
|
||||
.monaco-workbench .notebookOverlay .monaco-list:focus-within .markdown-cell-row.focused.${this.className}:after {
|
||||
border-color: ${borderColor} !important;
|
||||
}`);
|
||||
}
|
||||
}
|
||||
|
||||
private _resolveValue(value: string | ThemeColor): string {
|
||||
if (isThemeColor(value)) {
|
||||
const color = this._theme.getColor(value.id);
|
||||
if (color) {
|
||||
return color.toString();
|
||||
}
|
||||
return 'transparent';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._styleSheet.unref();
|
||||
}
|
||||
}
|
||||
|
||||
const enum CellDecorationCSSRuleType {
|
||||
ClassName = 0,
|
||||
}
|
||||
|
||||
class CSSNameHelper {
|
||||
|
||||
public static getClassName(key: string, type: CellDecorationCSSRuleType): string {
|
||||
return 'nb-' + key + '-' + type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import { NotebookKernelProviderAssociationRegistry, NotebookViewTypesExtensionRe
|
||||
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellEditType, CellKind, CellOutputKind, DisplayOrderKey, ICellEditOperation, IDisplayOutput, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, NotebookCellOutputsSplice, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellEditType, CellKind, CellOutputKind, DisplayOrderKey, ICellEditOperation, IDisplayOutput, INotebookDecorationRenderOptions, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, NotebookCellOutputsSplice, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer';
|
||||
import { NotebookEditorDescriptor, NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
|
||||
import { IMainNotebookController, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
@@ -261,6 +261,7 @@ export class NotebookService extends Disposable implements INotebookService, ICu
|
||||
private _lastClipboardIsCopy: boolean = true;
|
||||
|
||||
private _displayOrder: { userOrder: string[], defaultOrder: string[] } = Object.create(null);
|
||||
private readonly _decorationOptionProviders = new Map<string, INotebookDecorationRenderOptions>();
|
||||
|
||||
constructor(
|
||||
@IExtensionService private readonly _extensionService: IExtensionService,
|
||||
@@ -519,6 +520,24 @@ export class NotebookService extends Disposable implements INotebookService, ICu
|
||||
|
||||
}
|
||||
|
||||
registerEditorDecorationType(key: string, options: INotebookDecorationRenderOptions): void {
|
||||
if (this._decorationOptionProviders.has(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._decorationOptionProviders.set(key, options);
|
||||
}
|
||||
|
||||
removeEditorDecorationType(key: string): void {
|
||||
this._decorationOptionProviders.delete(key);
|
||||
|
||||
this.listNotebookEditors().forEach(editor => editor.removeEditorDecorations(key));
|
||||
}
|
||||
|
||||
resolveEditorDecorationOptions(key: string): INotebookDecorationRenderOptions | undefined {
|
||||
return this._decorationOptionProviders.get(key);
|
||||
}
|
||||
|
||||
getViewTypes(): ICustomEditorInfo[] {
|
||||
return [...this.notebookProviderInfoStore].map(info => ({
|
||||
id: info.id,
|
||||
|
||||
@@ -418,6 +418,7 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
|
||||
const titleMenu = disposables.add(this.cellMenus.getCellTitleMenu(contextKeyService));
|
||||
|
||||
const templateData: MarkdownCellRenderTemplate = {
|
||||
rootContainer,
|
||||
collapsedPart,
|
||||
expandButton,
|
||||
contextKeyService,
|
||||
@@ -471,6 +472,17 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
|
||||
}
|
||||
|
||||
renderElement(element: MarkdownCellViewModel, index: number, templateData: MarkdownCellRenderTemplate, height: number | undefined): void {
|
||||
const removedClassNames: string[] = [];
|
||||
templateData.rootContainer.classList.forEach(className => {
|
||||
if (/^nb\-.*$/.test(className)) {
|
||||
removedClassNames.push(className);
|
||||
}
|
||||
});
|
||||
|
||||
removedClassNames.forEach(className => {
|
||||
templateData.rootContainer.classList.remove(className);
|
||||
});
|
||||
|
||||
this.commonRenderElement(element, templateData);
|
||||
|
||||
templateData.currentRenderedCell = element;
|
||||
@@ -700,6 +712,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
|
||||
const titleMenu = disposables.add(this.cellMenus.getCellTitleMenu(contextKeyService));
|
||||
|
||||
const templateData: CodeCellRenderTemplate = {
|
||||
rootContainer,
|
||||
editorPart,
|
||||
collapsedPart,
|
||||
expandButton,
|
||||
@@ -808,14 +821,14 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
|
||||
|
||||
renderElement(element: CodeCellViewModel, index: number, templateData: CodeCellRenderTemplate, height: number | undefined): void {
|
||||
const removedClassNames: string[] = [];
|
||||
templateData.container.classList.forEach(className => {
|
||||
templateData.rootContainer.classList.forEach(className => {
|
||||
if (/^nb\-.*$/.test(className)) {
|
||||
removedClassNames.push(className);
|
||||
}
|
||||
});
|
||||
|
||||
removedClassNames.forEach(className => {
|
||||
templateData.container.classList.remove(className);
|
||||
templateData.rootContainer.classList.remove(className);
|
||||
});
|
||||
|
||||
this.commonRenderElement(element, templateData);
|
||||
|
||||
@@ -223,7 +223,7 @@ export class CodeCell extends Disposable {
|
||||
this._register(viewCell.onCellDecorationsChanged((e) => {
|
||||
e.added.forEach(options => {
|
||||
if (options.className) {
|
||||
DOM.addClass(templateData.container, options.className);
|
||||
DOM.addClass(templateData.rootContainer, options.className);
|
||||
}
|
||||
|
||||
if (options.outputClassName) {
|
||||
@@ -233,7 +233,7 @@ export class CodeCell extends Disposable {
|
||||
|
||||
e.removed.forEach(options => {
|
||||
if (options.className) {
|
||||
DOM.removeClass(templateData.container, options.className);
|
||||
DOM.removeClass(templateData.rootContainer, options.className);
|
||||
}
|
||||
|
||||
if (options.outputClassName) {
|
||||
@@ -245,7 +245,7 @@ export class CodeCell extends Disposable {
|
||||
|
||||
viewCell.getCellDecorations().forEach(options => {
|
||||
if (options.className) {
|
||||
DOM.addClass(templateData.container, options.className);
|
||||
DOM.addClass(templateData.rootContainer, options.className);
|
||||
}
|
||||
|
||||
if (options.outputClassName) {
|
||||
|
||||
@@ -109,13 +109,13 @@ export class StatefulMarkdownCell extends Disposable {
|
||||
this._register(viewCell.onCellDecorationsChanged((e) => {
|
||||
e.added.forEach(options => {
|
||||
if (options.className) {
|
||||
DOM.addClass(templateData.container, options.className);
|
||||
DOM.addClass(templateData.rootContainer, options.className);
|
||||
}
|
||||
});
|
||||
|
||||
e.removed.forEach(options => {
|
||||
if (options.className) {
|
||||
DOM.removeClass(templateData.container, options.className);
|
||||
DOM.removeClass(templateData.rootContainer, options.className);
|
||||
}
|
||||
});
|
||||
}));
|
||||
@@ -124,7 +124,7 @@ export class StatefulMarkdownCell extends Disposable {
|
||||
|
||||
viewCell.getCellDecorations().forEach(options => {
|
||||
if (options.className) {
|
||||
DOM.addClass(templateData.container, options.className);
|
||||
DOM.addClass(templateData.rootContainer, options.className);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IFileStatWithMetadata } from 'vs/platform/files/common/files';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
export enum CellKind {
|
||||
Markdown = 1,
|
||||
@@ -883,3 +884,9 @@ export const enum CellStatusbarAlignment {
|
||||
LEFT,
|
||||
RIGHT
|
||||
}
|
||||
|
||||
export interface INotebookDecorationRenderOptions {
|
||||
backgroundColor?: string | ThemeColor;
|
||||
borderColor?: string | ThemeColor;
|
||||
top?: editorCommon.IContentDecorationRenderOptions;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.pr
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import {
|
||||
INotebookTextModel, INotebookRendererInfo,
|
||||
IEditor, ICellEditOperation, NotebookCellOutputsSplice, INotebookKernelProvider, INotebookKernelInfo2, TransientMetadata, NotebookDataDto, TransientOptions
|
||||
IEditor, ICellEditOperation, NotebookCellOutputsSplice, INotebookKernelProvider, INotebookKernelInfo2, TransientMetadata, NotebookDataDto, TransientOptions, INotebookDecorationRenderOptions
|
||||
} from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
@@ -78,5 +78,7 @@ export interface INotebookService {
|
||||
listNotebookEditors(): readonly IEditor[];
|
||||
listVisibleNotebookEditors(): readonly IEditor[];
|
||||
listNotebookDocuments(): readonly NotebookTextModel[];
|
||||
|
||||
registerEditorDecorationType(key: string, options: INotebookDecorationRenderOptions): void;
|
||||
removeEditorDecorationType(key: string): void;
|
||||
resolveEditorDecorationOptions(key: string): INotebookDecorationRenderOptions | undefined;
|
||||
}
|
||||
|
||||
@@ -66,6 +66,12 @@ export class TestNotebookEditor implements INotebookEditor {
|
||||
|
||||
constructor(
|
||||
) { }
|
||||
setEditorDecorations(key: string, range: ICellRange): void {
|
||||
// throw new Error('Method not implemented.');
|
||||
}
|
||||
removeEditorDecorations(key: string): void {
|
||||
// throw new Error('Method not implemented.');
|
||||
}
|
||||
getSelectionHandles(): number[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user