From db5cb92a74690790c207b792404aeea42ce270c6 Mon Sep 17 00:00:00 2001 From: Valeriy Sidorenko Date: Mon, 19 Apr 2021 19:40:47 +0300 Subject: [PATCH 01/76] fix: use addListener instead of addEventListener to observe media query lists Prior Safari 14, MediaQueryList does not have method addEventListener, use addListener for backward compatibility, which is supported by all browsers. fixes https://github.com/microsoft/monaco-editor/issues/2432 --- .../browser/standaloneThemeServiceImpl.ts | 10 ++++++++-- .../browser/browserHostColorSchemeService.ts | 16 +++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts index 180961e72fd..a9abc5fdf15 100644 --- a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts +++ b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts @@ -233,9 +233,15 @@ export class StandaloneThemeServiceImpl extends Disposable implements IStandalon this._updateCSS(); }); - window.matchMedia('(forced-colors: active)').addEventListener('change', () => { + const matchForcedColors = window.matchMedia('(forced-colors: active)'); + const matchForcedColorsListener = () => { this._updateActualTheme(); - }); + }; + if (typeof matchForcedColors.addEventListener === 'function') { + matchForcedColors.addEventListener('change', matchForcedColorsListener); + } else { + matchForcedColors.addListener(matchForcedColorsListener); + } } public registerEditorContainer(domNode: HTMLElement): IDisposable { diff --git a/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts b/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts index f3ce7567fa4..37636a771ed 100644 --- a/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts +++ b/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts @@ -25,12 +25,18 @@ export class BrowserHostColorSchemeService extends Disposable implements IHostCo private registerListeners(): void { - window.matchMedia('(prefers-color-scheme: dark)').addListener(() => { + const matchPrefersColorSchemeDark = window.matchMedia('(prefers-color-scheme: dark)'); + const matchForcedColors = window.matchMedia('(forced-colors: active)'); + const listener = () => { this._onDidSchemeChangeEvent.fire(); - }); - window.matchMedia('(forced-colors: active)').addListener(() => { - this._onDidSchemeChangeEvent.fire(); - }); + }; + if (typeof matchForcedColors.addEventListener === 'function') { + matchPrefersColorSchemeDark.addEventListener('change', listener); + matchForcedColors.addEventListener('change', listener); + } else { + matchPrefersColorSchemeDark.addListener(listener); + matchForcedColors.addListener(listener); + } } get onDidChangeColorScheme(): Event { From d4e6b16a6342cb201524b3b7df226c3b8c48c311 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 13:27:57 -0700 Subject: [PATCH 02/76] move layout constants to notebook options. --- .vscode/notebooks/endgame.github-issues | 2 +- .../contrib/notebook/browser/constants.ts | 38 ----- .../notebook/browser/diff/diffComponents.ts | 7 +- .../browser/diff/notebookDiffEditorBrowser.ts | 2 + .../browser/diff/notebookTextDiffEditor.ts | 36 +++-- .../notebook/browser/notebookBrowser.ts | 2 + .../notebook/browser/notebookEditorWidget.ts | 137 +++++++++++------- .../browser/view/renderers/cellDnd.ts | 7 +- .../view/renderers/cellEditorOptions.ts | 8 +- .../browser/view/renderers/cellRenderer.ts | 27 ++-- .../browser/view/renderers/codeCell.ts | 3 +- .../browser/view/renderers/markdownCell.ts | 3 +- .../browser/viewModel/baseCellViewModel.ts | 5 +- .../browser/viewModel/codeCellViewModel.ts | 60 ++++++-- .../browser/viewModel/eventDispatcher.ts | 3 +- .../viewModel/markdownCellViewModel.ts | 32 ++-- .../contrib/notebook/common/notebookCommon.ts | 19 +++ .../notebook/common/notebookOptions.ts | 56 +++++++ .../notebook/test/notebookViewModel.test.ts | 3 +- .../notebook/test/testNotebookEditor.ts | 3 +- 20 files changed, 296 insertions(+), 157 deletions(-) create mode 100644 src/vs/workbench/contrib/notebook/common/notebookOptions.ts diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index 881af2c14b4..bc2fba29ddf 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -7,7 +7,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-js-debug repo:microsoft/vscode-remote-release repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-remotehub\n\n$MILESTONE=milestone:\"April 2021\"" + "value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-js-debug repo:microsoft/vscode-remote-release repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-remotehub\n\n$MILESTONE=milestone:\"May 2021\"" }, { "kind": 1, diff --git a/src/vs/workbench/contrib/notebook/browser/constants.ts b/src/vs/workbench/contrib/notebook/browser/constants.ts index 06627113262..5ed8e659f83 100644 --- a/src/vs/workbench/contrib/notebook/browser/constants.ts +++ b/src/vs/workbench/contrib/notebook/browser/constants.ts @@ -6,41 +6,3 @@ // Scrollable Element export const SCROLLABLE_ELEMENT_PADDING_TOP = 20; -// export const SCROLLABLE_ELEMENT_PADDING_TOP_WITH_TOOLBAR = 8; - -// Code cell layout: -// [CODE_CELL_LEFT_MARGIN][CELL_RUN_GUTTER][editorWidth][CELL_RIGHT_MARGIN] - -// Markdown cell layout: -// [CELL_MARGIN][content][CELL_RIGHT_MARGIN] - -// Markdown editor cell layout: -// [CODE_CELL_LEFT_MARGIN][content][CELL_RIGHT_MARGIN] - -// Cell sizing related -export const CELL_RIGHT_MARGIN = 16; -export const CELL_RUN_GUTTER = 28; -export const CODE_CELL_LEFT_MARGIN = 32; - -export const EDITOR_TOOLBAR_HEIGHT = 0; -export const BOTTOM_CELL_TOOLBAR_GAP = 18; -export const BOTTOM_CELL_TOOLBAR_HEIGHT = 22; -export const CELL_STATUSBAR_HEIGHT = 22; - -// Margin above editor -export const CELL_TOP_MARGIN = 6; -export const CELL_BOTTOM_MARGIN = 6; - -export const MARKDOWN_CELL_TOP_MARGIN = 8; -export const MARKDOWN_CELL_BOTTOM_MARGIN = 8; - -// Top and bottom padding inside the monaco editor in a cell, which are included in `cell.editorHeight` -// export const EDITOR_TOP_PADDING = 12; -export const EDITOR_BOTTOM_PADDING = 4; -export const EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR = 12; - -export const CELL_OUTPUT_PADDING = 14; - -export const COLLAPSED_INDICATOR_HEIGHT = 24; - -export const MARKDOWN_PREVIEW_PADDING = 8; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 3b095c3039b..5cb5beb2cb4 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -10,7 +10,6 @@ import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/edit import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { DiffElementViewModelBase, getFormatedMetadataJSON, OUTPUT_EDITOR_HEIGHT_MAGIC, PropertyFoldingState, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel'; import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DiffSide, DIFF_CELL_MARGIN, INotebookTextDiffEditor, NOTEBOOK_DIFF_CELL_PROPERTY, NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; -import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -980,7 +979,7 @@ export class DeletedElement extends SingleSideDiffElement { const originalCell = this.cell.original!; const lineCount = originalCell.textModel.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; - const editorHeight = lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING; + const editorHeight = lineCount * lineHeight + getEditorTopPadding() + this.notebookEditor.notebookOptions.getLayoutConfiguration().editorBottomPadding; this._editor = this.templateData.sourceEditor; this._editor.layout({ @@ -1131,7 +1130,7 @@ export class InsertElement extends SingleSideDiffElement { const modifiedCell = this.cell.modified!; const lineCount = modifiedCell.textModel.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; - const editorHeight = lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING; + const editorHeight = lineCount * lineHeight + getEditorTopPadding() + this.notebookEditor.notebookOptions.getLayoutConfiguration().editorBottomPadding; this._editor = this.templateData.sourceEditor; this._editor.layout( @@ -1469,7 +1468,7 @@ export class ModifiedElement extends AbstractElementRenderer { const modifiedCell = this.cell.modified!; const lineCount = modifiedCell.textModel.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; - const editorHeight = this.cell.layoutInfo.editorHeight !== 0 ? this.cell.layoutInfo.editorHeight : lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING; + const editorHeight = this.cell.layoutInfo.editorHeight !== 0 ? this.cell.layoutInfo.editorHeight : lineCount * lineHeight + getEditorTopPadding() + this.notebookEditor.notebookOptions.getLayoutConfiguration().editorBottomPadding; this._editorContainer = this.templateData.editorContainer; this._editor = this.templateData.sourceEditor; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts index 0ca043aacff..9685efbaec3 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts @@ -15,6 +15,7 @@ import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; export enum DiffSide { Original = 0, @@ -26,6 +27,7 @@ export interface IDiffCellInfo extends ICommonCellInfo { } export interface INotebookTextDiffEditor extends ICommonNotebookEditor { + notebookOptions: NotebookOptions; readonly textModel?: NotebookTextModel; onMouseUp: Event<{ readonly event: MouseEvent; readonly target: DiffElementViewModelBase; }>; onDidDynamicOutputRendered: Event<{ cell: IGenericCellViewModel, output: ICellOutputViewModel }>; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index cf5718517bd..2b75f4f1716 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -38,9 +38,9 @@ import { generateUuid } from 'vs/base/common/uuid'; import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel'; import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView'; -import { CELL_OUTPUT_PADDING, MARKDOWN_PREVIEW_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { NotebookDiffEditorEventDispatcher, NotebookDiffLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/diff/eventDispatcher'; import { readFontInfo } from 'vs/editor/browser/config/configuration'; +import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; const $ = DOM.$; @@ -75,6 +75,12 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD protected _onDidDynamicOutputRendered = new Emitter<{ cell: IGenericCellViewModel, output: ICellOutputViewModel }>(); onDidDynamicOutputRendered = this._onDidDynamicOutputRendered.event; + private _notebookOptions = new NotebookOptions(); + + get notebookOptions() { + return this._notebookOptions; + } + private readonly _localStore = this._register(new DisposableStore()); private _isDisposed: boolean = false; @@ -96,7 +102,6 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD const editorOptions = this.configurationService.getValue('editor'); this._fontInfo = readFontInfo(BareFontInfo.createFromRawSettings(editorOptions, getZoomLevel(), getPixelRatio())); this._revealFirst = true; - this._outputRenderer = new OutputRenderer(this, this.instantiationService); } @@ -366,21 +371,19 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD })); } - private readonly webviewOptions = { - outputNodePadding: CELL_OUTPUT_PADDING, - outputNodeLeftPadding: 32, - previewNodePadding: MARKDOWN_PREVIEW_PADDING, - leftMargin: 0, - rightMargin: 0, - runGutter: 0 - }; - private async _createModifiedWebview(id: string, resource: URI): Promise { if (this._modifiedWebview) { this._modifiedWebview.dispose(); } - this._modifiedWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, this.webviewOptions) as BackLayerWebView; + this._modifiedWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, { + outputNodePadding: this._notebookOptions.getLayoutConfiguration().cellOutputPadding, // CELL_OUTPUT_PADDING, + outputNodeLeftPadding: 32, + previewNodePadding: this._notebookOptions.getLayoutConfiguration().markdownPreviewPadding, // MARKDOWN_PREVIEW_PADDING, + leftMargin: 0, + rightMargin: 0, + runGutter: 0 + }) as BackLayerWebView; // attach the webview container to the DOM tree first this._list.rowsContainer.insertAdjacentElement('afterbegin', this._modifiedWebview.element); await this._modifiedWebview.createWebview(); @@ -393,7 +396,14 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._originalWebview.dispose(); } - this._originalWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, this.webviewOptions) as BackLayerWebView; + this._originalWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, { + outputNodePadding: this._notebookOptions.getLayoutConfiguration().cellOutputPadding, // CELL_OUTPUT_PADDING, + outputNodeLeftPadding: 32, + previewNodePadding: this._notebookOptions.getLayoutConfiguration().markdownPreviewPadding, // MARKDOWN_PREVIEW_PADDING, + leftMargin: 0, + rightMargin: 0, + runGutter: 0 + }) as BackLayerWebView; // attach the webview container to the DOM tree first this._list.rowsContainer.insertAdjacentElement('afterbegin', this._originalWebview.element); await this._originalWebview.createWebview(); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index ac887b9a8f0..57fb30b69d1 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -31,6 +31,7 @@ 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'; import { INotebookWebviewMessage } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView'; +import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; export const NOTEBOOK_EDITOR_ID = 'workbench.editor.notebook'; export const NOTEBOOK_DIFF_EDITOR_ID = 'workbench.editor.notebookTextDiffEditor'; @@ -382,6 +383,7 @@ export interface INotebookEditor extends ICommonNotebookEditor { readonly onDidScroll: Event; readonly onDidChangeActiveCell: Event; + readonly notebookOptions: NotebookOptions; isDisposed: boolean; dispose(): void; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index a5495997673..7ba96f5e66b 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -42,7 +42,6 @@ import { IEditorMemento } from 'vs/workbench/common/editor'; import { Memento, MementoObject } from 'vs/workbench/common/memento'; import { PANEL_BORDER } from 'vs/workbench/common/theme'; import { debugIconStartForeground } from 'vs/workbench/contrib/debug/browser/debugColors'; -import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_OUTPUT_PADDING, CELL_RIGHT_MARGIN, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, MARKDOWN_CELL_BOTTOM_MARGIN, MARKDOWN_CELL_TOP_MARGIN, MARKDOWN_PREVIEW_PADDING, SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants'; import { CellEditState, CellFocusMode, IActiveNotebookEditor, ICellOutputViewModel, ICellViewModel, ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IFocusNotebookCellOptions, IGenericCellViewModel, IInsetRenderOutput, INotebookCellList, INotebookCellOutputLayoutInfo, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorMouseEvent, NotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_ID, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookDecorationCSSRules, NotebookRefCountedStyleSheet } from 'vs/workbench/contrib/notebook/browser/notebookEditorDecorations'; import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions'; @@ -75,6 +74,8 @@ import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance'; import { readFontInfo } from 'vs/editor/browser/config/configuration'; import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { NotebookEditorContextKeys } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidgetContextKeys'; +import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; +import { SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants'; const $ = DOM.$; @@ -306,6 +307,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor public readonly scopedContextKeyService: IContextKeyService; private readonly instantiationService: IInstantiationService; + private readonly _notebookOptions: NotebookOptions; + + get notebookOptions() { + return this._notebookOptions; + } constructor( readonly creationOptions: INotebookEditorCreationOptions, @@ -330,6 +336,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this.isEmbedded = creationOptions.isEmbedded || false; this.useRenderer = !isWeb && !!this.configurationService.getValue(ExperimentalUseMarkdownRenderer) && !accessibilityService.isScreenReaderOptimized(); + this._notebookOptions = new NotebookOptions(); this._overlayContainer = document.createElement('div'); this.scopedContextKeyService = contextKeyService.createScoped(this._overlayContainer); @@ -547,15 +554,81 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._notebookTopToolbarContainer.style.display = 'none'; DOM.append(parent, this._notebookTopToolbarContainer); this._body = document.createElement('div'); - this._body.classList.add('cell-list-container'); - this._createCellList(); DOM.append(parent, this._body); + this._body.classList.add('cell-list-container'); + this._createLayoutStyles(); + this._createCellList(); this._overflowContainer = document.createElement('div'); this._overflowContainer.classList.add('notebook-overflow-widget-container', 'monaco-editor'); DOM.append(parent, this._overflowContainer); } + private _createLayoutStyles(): void { + const styleElement = DOM.createStyleSheet(this._body); + const styleSheet = new NotebookRefCountedStyleSheet({ + removeEditorStyleSheets: (key) => { + // this._editorStyleSheets.delete(key); + if (key === 'notebook-layout-styles') { + if (styleElement && styleElement.parentElement) { + styleElement.parentElement.removeChild(styleElement); + } + } + } + }, 'notebook-layout-style', styleElement); + styleSheet.ref(); + // Cell Margin + + const cellRightMargin = this._notebookOptions.getLayoutConfiguration().cellRightMargin; + const cellTopMargin = this._notebookOptions.getLayoutConfiguration().cellTopMargin; + const cellRunGutter = this._notebookOptions.getLayoutConfiguration().cellRunGutter; + const cellBottomMargin = this._notebookOptions.getLayoutConfiguration().cellBottomMargin; + const codeCellLeftMargin = this._notebookOptions.getLayoutConfiguration().codeCellLeftMargin; + const markdownCellBottomMargin = this._notebookOptions.getLayoutConfiguration().markdownCellBottomMargin; + const markdownCellTopMargin = this._notebookOptions.getLayoutConfiguration().markdownCellTopMargin; + const bottomCellToolbarGap = this._notebookOptions.getLayoutConfiguration().bottomCellToolbarGap; + const bottomCellToolbarHeight = this._notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight; + const collapsedIndicatorHeight = this._notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight; + styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row div.cell.code { margin-left: ${codeCellLeftMargin}px; }`); + styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .code-cell-row div.cell.code { margin-left: ${codeCellLeftMargin + cellRunGutter}px; }`); + styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell { margin-right: ${cellRightMargin}px; }`); + styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > .cell-inner-container { padding-top: ${cellTopMargin}px; }`); + styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container { padding-bottom: ${markdownCellBottomMargin}px; padding-top: ${markdownCellTopMargin}px; }`); + styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container.webview-backed-markdown-cell { padding: 0; }`); + styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .webview-backed-markdown-cell.markdown-cell-edit-mode .cell.code { padding-bottom: ${markdownCellBottomMargin}px; padding-top: ${markdownCellTopMargin}px; }`); + styleSheet.insertRule(`.notebookOverlay .output { margin: 0px ${cellRightMargin}px 0px ${codeCellLeftMargin + cellRunGutter}px; }`); + styleSheet.insertRule(`.notebookOverlay .output { width: calc(100% - ${codeCellLeftMargin + cellRunGutter + cellRightMargin}px); }`); + + styleSheet.insertRule(`.notebookOverlay .output-show-more-container { margin: 0px ${cellRightMargin}px 0px ${codeCellLeftMargin + cellRunGutter}px; }`); + styleSheet.insertRule(`.notebookOverlay .output-show-more-container { width: calc(100% - ${codeCellLeftMargin + cellRunGutter + cellRightMargin}px); }`); + + styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell.markdown { padding-left: ${cellRunGutter}px; }`); + styleSheet.insertRule(`.notebookOverlay .cell .run-button-container { width: 20px; left: ${codeCellLeftMargin + Math.floor(cellRunGutter - 20) / 2}px }`); + styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row :not(.webview-backed-markdown-cell) .cell-focus-indicator-top { height: ${cellTopMargin}px; }`); + styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { bottom: ${bottomCellToolbarGap}px; }`); + styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-focus-indicator-left, + .notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-drag-handle { width: ${codeCellLeftMargin + cellRunGutter}px; }`); + styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row .cell-focus-indicator-left { width: ${codeCellLeftMargin}px; }`); + styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator.cell-focus-indicator-right { width: ${cellRightMargin}px; }`); + styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-bottom { height: ${cellBottomMargin}px; }`); + styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-shadow-container-bottom { top: ${cellBottomMargin}px; }`); + + styleSheet.insertRule(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-collapsed-part { margin-left: ${codeCellLeftMargin + cellRunGutter}px; height: ${collapsedIndicatorHeight}px; }`); + styleSheet.insertRule(`.notebookOverlay .cell-list-top-cell-toolbar-container { top: -${SCROLLABLE_ELEMENT_PADDING_TOP}px }`); + + styleSheet.insertRule(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container { height: ${bottomCellToolbarHeight}px }`); + styleSheet.insertRule(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .cell-list-top-cell-toolbar-container { height: ${bottomCellToolbarHeight}px }`); + + // left and right border margins + styleSheet.insertRule(` + .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.focused .cell-focus-indicator-left:before, + .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.focused .cell-focus-indicator-right:before, + .monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-left:before, + .monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-right:before { + top: -${cellTopMargin}px; height: calc(100% + ${cellTopMargin + cellBottomMargin}px) + }`); + } + private _createCellList(): void { this._body.classList.add('cell-list-container'); @@ -1076,13 +1149,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } private async _createWebview(id: string, resource: URI): Promise { + const layoutConfiguration = this._notebookOptions.getLayoutConfiguration(); this._webview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, { - outputNodePadding: CELL_OUTPUT_PADDING, - outputNodeLeftPadding: CELL_OUTPUT_PADDING, - previewNodePadding: MARKDOWN_PREVIEW_PADDING, - leftMargin: CODE_CELL_LEFT_MARGIN, - rightMargin: CELL_RIGHT_MARGIN, - runGutter: CELL_RUN_GUTTER, + outputNodePadding: layoutConfiguration.cellOutputPadding, // CELL_OUTPUT_PADDING, + outputNodeLeftPadding: layoutConfiguration.cellOutputPadding, // CELL_OUTPUT_PADDING, + previewNodePadding: layoutConfiguration.markdownPreviewPadding, // MARKDOWN_PREVIEW_PADDING, + leftMargin: layoutConfiguration.codeCellLeftMargin, // CODE_CELL_LEFT_MARGIN, + rightMargin: layoutConfiguration.cellRightMargin, // CELL_RIGHT_MARGIN, + runGutter: layoutConfiguration.cellRunGutter, // CELL_RUN_GUTTER, }); this._webview.element.style.width = '100%'; @@ -1093,7 +1167,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private async _attachModel(textModel: NotebookTextModel, viewState: INotebookEditorViewState | undefined) { await this._createWebview(this.getId(), textModel.uri); - this._eventDispatcher = new NotebookEventDispatcher(); + this._eventDispatcher = new NotebookEventDispatcher(this._notebookOptions); this.viewModel = this.instantiationService.createInstance(NotebookViewModel, textModel.viewType, textModel, this._eventDispatcher, this.getLayoutInfo()); this._eventDispatcher.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]); @@ -2385,9 +2459,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor updateMarkdownCellHeight(cellId: string, height: number, isInit: boolean) { const cell = this.getCellById(cellId); + const layoutConfiguration = this._notebookOptions.getLayoutConfiguration(); if (cell && cell instanceof MarkdownCellViewModel) { - if (height + BOTTOM_CELL_TOOLBAR_GAP !== cell.layoutInfo.totalHeight) { - this._debug('updateMarkdownCellHeight', cell.handle, height + BOTTOM_CELL_TOOLBAR_GAP, isInit); + if (height + layoutConfiguration.bottomCellToolbarGap !== cell.layoutInfo.totalHeight) { + this._debug('updateMarkdownCellHeight', cell.handle, height + layoutConfiguration.bottomCellToolbarGap, isInit); cell.renderedMarkdownHeight = height; } } @@ -2822,43 +2897,5 @@ registerThemingParticipant((theme, collector) => { }`); } - // Cell Margin - collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row div.cell.code { margin-left: ${CODE_CELL_LEFT_MARGIN}px; }`); - collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .code-cell-row div.cell.code { margin-left: ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; }`); - collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell { margin-right: ${CELL_RIGHT_MARGIN}px; }`); - collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > .cell-inner-container { padding-top: ${CELL_TOP_MARGIN}px; }`); - collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container { padding-bottom: ${MARKDOWN_CELL_BOTTOM_MARGIN}px; padding-top: ${MARKDOWN_CELL_TOP_MARGIN}px; }`); - collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container.webview-backed-markdown-cell { padding: 0; }`); - collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .webview-backed-markdown-cell.markdown-cell-edit-mode .cell.code { padding-bottom: ${MARKDOWN_CELL_BOTTOM_MARGIN}px; padding-top: ${MARKDOWN_CELL_TOP_MARGIN}px; }`); - collector.addRule(`.notebookOverlay .output { margin: 0px ${CELL_RIGHT_MARGIN}px 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; }`); - collector.addRule(`.notebookOverlay .output { width: calc(100% - ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER + CELL_RIGHT_MARGIN}px); }`); - collector.addRule(`.notebookOverlay .output-show-more-container { margin: 0px ${CELL_RIGHT_MARGIN}px 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; }`); - collector.addRule(`.notebookOverlay .output-show-more-container { width: calc(100% - ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER + CELL_RIGHT_MARGIN}px); }`); - - collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell.markdown { padding-left: ${CELL_RUN_GUTTER}px; }`); - collector.addRule(`.notebookOverlay .cell .run-button-container { width: 20px; left: ${CODE_CELL_LEFT_MARGIN + Math.floor(CELL_RUN_GUTTER - 20) / 2}px }`); - collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row :not(.webview-backed-markdown-cell) .cell-focus-indicator-top { height: ${CELL_TOP_MARGIN}px; }`); - collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { bottom: ${BOTTOM_CELL_TOOLBAR_GAP}px; }`); - collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-focus-indicator-left, - .notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-drag-handle { width: ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; }`); - collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row .cell-focus-indicator-left { width: ${CODE_CELL_LEFT_MARGIN}px; }`); - collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator.cell-focus-indicator-right { width: ${CELL_RIGHT_MARGIN}px; }`); - collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-bottom { height: ${CELL_BOTTOM_MARGIN}px; }`); - collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-shadow-container-bottom { top: ${CELL_BOTTOM_MARGIN}px; }`); - - collector.addRule(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-collapsed-part { margin-left: ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; height: ${COLLAPSED_INDICATOR_HEIGHT}px; }`); - collector.addRule(`.notebookOverlay .cell-list-top-cell-toolbar-container { top: -${SCROLLABLE_ELEMENT_PADDING_TOP}px }`); - - 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 }`); - collector.addRule(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .cell-list-top-cell-toolbar-container { height: ${BOTTOM_CELL_TOOLBAR_HEIGHT}px }`); - - // left and right border margins - collector.addRule(` - .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.focused .cell-focus-indicator-left:before, - .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.focused .cell-focus-indicator-right:before, - .monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-left:before, - .monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-right:before { - top: -${CELL_TOP_MARGIN}px; height: calc(100% + ${CELL_TOP_MARGIN + CELL_BOTTOM_MARGIN}px) - }`); }); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellDnd.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellDnd.ts index 64265f4477a..fca5bd43ce6 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellDnd.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellDnd.ts @@ -9,7 +9,6 @@ import { domEvent } from 'vs/base/browser/event'; import { Delayer } from 'vs/base/common/async'; import { Disposable } from 'vs/base/common/lifecycle'; import * as platform from 'vs/base/common/platform'; -import { BOTTOM_CELL_TOOLBAR_GAP } from 'vs/workbench/contrib/notebook/browser/constants'; import { BaseCellRenderTemplate, expandCellRangesWithHiddenCells, ICellViewModel, INotebookCellList, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { cloneNotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { CellEditType, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; @@ -157,7 +156,8 @@ export class CellDragAndDropController extends Disposable { } private updateInsertIndicator(dropDirection: string, insertionIndicatorAbsolutePos: number) { - const insertionIndicatorTop = insertionIndicatorAbsolutePos - this.list.scrollTop + BOTTOM_CELL_TOOLBAR_GAP / 2; + const layoutInfo = this.notebookEditor.notebookOptions.getLayoutConfiguration(); + const insertionIndicatorTop = insertionIndicatorAbsolutePos - this.list.scrollTop + layoutInfo.bottomCellToolbarGap / 2; if (insertionIndicatorTop >= 0) { this.listInsertionIndicator.style.top = `${insertionIndicatorTop}px`; this.setInsertIndicatorVisibility(true); @@ -199,7 +199,8 @@ export class CellDragAndDropController extends Disposable { const cellTop = this.list.getAbsoluteTopOfElement(draggedOverCell); const cellHeight = this.list.elementHeight(draggedOverCell); const insertionIndicatorAbsolutePos = dropDirection === 'above' ? cellTop : cellTop + cellHeight; - const insertionIndicatorTop = insertionIndicatorAbsolutePos - this.list.scrollTop + BOTTOM_CELL_TOOLBAR_GAP / 2; + const layoutInfo = this.notebookEditor.notebookOptions.getLayoutConfiguration(); + const insertionIndicatorTop = insertionIndicatorAbsolutePos - this.list.scrollTop + layoutInfo.bottomCellToolbarGap / 2; const editorHeight = this.notebookEditor.getDomNode().getBoundingClientRect().height; if (insertionIndicatorTop < 0 || insertionIndicatorTop > editorHeight) { // Ignore drop, insertion point is off-screen diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts index 78ffc778563..1a078ecf9d8 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts @@ -10,7 +10,6 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IEditorOptions, LineNumbersType } from 'vs/editor/common/config/editorOptions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { EDITOR_BOTTOM_PADDING, EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR } from 'vs/workbench/contrib/notebook/browser/constants'; import { EditorTopPaddingChangeEvent, getEditorTopPadding, getNotebookEditorFromEditorPane, ICellViewModel, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { localize } from 'vs/nls'; @@ -19,6 +18,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { NOTEBOOK_ACTIONS_CATEGORY } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions'; +import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; export class CellEditorOptions extends Disposable { @@ -48,7 +48,7 @@ export class CellEditorOptions extends Disposable { private readonly _onDidChange = new Emitter(); readonly onDidChange: Event = this._onDidChange.event; - constructor(readonly configurationService: IConfigurationService, language: string) { + constructor(readonly notebookOptions: NotebookOptions, readonly configurationService: IConfigurationService, language: string) { super(); this._register(configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('editor') || e.affectsConfiguration('notebook') || e.affectsConfiguration(ShowCellStatusBarKey)) { @@ -66,7 +66,9 @@ export class CellEditorOptions extends Disposable { const showCellStatusBar = configurationService.getValue(ShowCellStatusBarKey); const editorPadding = { top: getEditorTopPadding(), - bottom: showCellStatusBar ? EDITOR_BOTTOM_PADDING : EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR + bottom: showCellStatusBar + ? this.notebookOptions.getLayoutConfiguration().editorBottomPadding// EDITOR_BOTTOM_PADDING + : this.notebookOptions.getLayoutConfiguration().editorBottomPaddingWithoutStatusBar // EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR }; const renderLiNumbers = configurationService.getValue<'on' | 'off'>('notebook.lineNumbers') === 'on'; diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index d93c98350db..b4ce80acebc 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -35,7 +35,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { BOTTOM_CELL_TOOLBAR_GAP, CELL_BOTTOM_MARGIN, CELL_TOP_MARGIN, EDITOR_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants'; import { DeleteCellAction, INotebookActionContext, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions'; import { BaseCellRenderTemplate, CellEditState, CodeCellLayoutInfo, CodeCellRenderTemplate, EXPAND_CELL_INPUT_COMMAND_ID, ICellViewModel, INotebookEditor, isCodeCellRenderTemplate, MarkdownCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellContextKeyManager } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellContextKeys'; @@ -100,7 +99,7 @@ abstract class AbstractCellRenderer { language: string, protected dndController: CellDragAndDropController | undefined, ) { - this.editorOptions = new CellEditorOptions(configurationService, language); + this.editorOptions = new CellEditorOptions(notebookEditor.notebookOptions, configurationService, language); this.cellMenus = this.instantiationService.createInstance(CellMenus); } @@ -184,17 +183,18 @@ abstract class AbstractCellRenderer { this.notebookEditor.focus(); } + const layoutInfo = this.notebookEditor.notebookOptions.getLayoutConfiguration(); if (actions.primary.length || actions.secondary.length) { templateData.container.classList.add('cell-has-toolbar-actions'); if (isCodeCellRenderTemplate(templateData)) { - templateData.focusIndicatorLeft.style.top = `${EDITOR_TOOLBAR_HEIGHT + CELL_TOP_MARGIN}px`; - templateData.focusIndicatorRight.style.top = `${EDITOR_TOOLBAR_HEIGHT + CELL_TOP_MARGIN}px`; + templateData.focusIndicatorLeft.style.top = `${layoutInfo.editorToolbarHeight + layoutInfo.cellTopMargin}px`; + templateData.focusIndicatorRight.style.top = `${layoutInfo.editorToolbarHeight + layoutInfo.cellTopMargin}px`; } } else { templateData.container.classList.remove('cell-has-toolbar-actions'); if (isCodeCellRenderTemplate(templateData)) { - templateData.focusIndicatorLeft.style.top = `${CELL_TOP_MARGIN}px`; - templateData.focusIndicatorRight.style.top = `${CELL_TOP_MARGIN}px`; + templateData.focusIndicatorLeft.style.top = `${layoutInfo.cellTopMargin}px`; + templateData.focusIndicatorRight.style.top = `${layoutInfo.cellTopMargin}px`; } } }; @@ -467,7 +467,7 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR })); this.updateForHover(element, templateData); - const cellEditorOptions = new CellEditorOptions(this.configurationService, 'markdown'); + const cellEditorOptions = new CellEditorOptions(this.notebookEditor.notebookOptions, this.configurationService, 'markdown'); cellEditorOptions.setLineNumbers(element.lineNumbers); elementDisposables.add(cellEditorOptions); @@ -508,9 +508,9 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR } private updateForLayout(element: MarkdownCellViewModel, templateData: MarkdownCellRenderTemplate): void { - templateData.focusIndicatorBottom.style.top = `${element.layoutInfo.totalHeight - BOTTOM_CELL_TOOLBAR_GAP - CELL_BOTTOM_MARGIN}px`; - - const focusSideHeight = element.layoutInfo.totalHeight - BOTTOM_CELL_TOOLBAR_GAP; + const layoutInfo = this.notebookEditor.notebookOptions.getLayoutConfiguration(); + templateData.focusIndicatorBottom.style.top = `${element.layoutInfo.totalHeight - layoutInfo.bottomCellToolbarGap - layoutInfo.cellBottomMargin}px`; + const focusSideHeight = element.layoutInfo.totalHeight - layoutInfo.bottomCellToolbarGap; templateData.focusIndicatorLeft.style.height = `${focusSideHeight}px`; templateData.focusIndicatorRight.style.height = `${focusSideHeight}px`; } @@ -879,12 +879,13 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende } private updateForLayout(element: CodeCellViewModel, templateData: CodeCellRenderTemplate): void { + const layoutInfo = this.notebookEditor.notebookOptions.getLayoutConfiguration(); templateData.focusIndicatorLeft.style.height = `${element.layoutInfo.indicatorHeight}px`; templateData.focusIndicatorRight.style.height = `${element.layoutInfo.indicatorHeight}px`; - templateData.focusIndicatorBottom.style.top = `${element.layoutInfo.totalHeight - BOTTOM_CELL_TOOLBAR_GAP - CELL_BOTTOM_MARGIN}px`; + templateData.focusIndicatorBottom.style.top = `${element.layoutInfo.totalHeight - layoutInfo.bottomCellToolbarGap - layoutInfo.cellBottomMargin}px`; templateData.outputContainer.style.top = `${element.layoutInfo.outputContainerOffset}px`; templateData.outputShowMoreContainer.style.top = `${element.layoutInfo.outputShowMoreContainerOffset}px`; - templateData.dragHandle.style.height = `${element.layoutInfo.totalHeight - BOTTOM_CELL_TOOLBAR_GAP}px`; + templateData.dragHandle.style.height = `${element.layoutInfo.totalHeight - layoutInfo.bottomCellToolbarGap}px`; } renderElement(element: CodeCellViewModel, index: number, templateData: CodeCellRenderTemplate, height: number | undefined): void { @@ -938,7 +939,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende elementDisposables.add(this.instantiationService.createInstance(CodeCell, this.notebookEditor, element, templateData)); this.renderedEditors.set(element, templateData.editor); - const cellEditorOptions = new CellEditorOptions(this.configurationService, element.language); + const cellEditorOptions = new CellEditorOptions(this.notebookEditor.notebookOptions, this.configurationService, element.language); elementDisposables.add(cellEditorOptions); elementDisposables.add(cellEditorOptions.onDidChange(newValue => templateData.editor.updateOptions(newValue))); templateData.editor.updateOptions(cellEditorOptions.value); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index 8cbe4509cb1..9a49ddec4f7 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -10,7 +10,6 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IDimension } from 'vs/editor/common/editorCommon'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CellFocusMode, CodeCellRenderTemplate, getEditorTopPadding, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellOutputContainer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellOutput'; import { ClickTargetType } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; @@ -41,7 +40,7 @@ export class CodeCell extends Disposable { const lineNum = this.viewCell.lineCount; const lineHeight = this.viewCell.layoutInfo.fontInfo?.lineHeight || 17; const editorHeight = this.viewCell.layoutInfo.editorHeight === 0 - ? lineNum * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING + ? lineNum * lineHeight + getEditorTopPadding() + this.notebookEditor.notebookOptions.getLayoutConfiguration().editorBottomPadding // EDITOR_BOTTOM_PADDING : this.viewCell.layoutInfo.editorHeight; this.layoutEditor( diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index 8cb61486064..a12a464e70d 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -10,7 +10,6 @@ import { Disposable, DisposableStore, IDisposable, MutableDisposable, toDisposab import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { CellEditState, CellFocusMode, MarkdownCellRenderTemplate, ICellViewModel, getEditorTopPadding, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellFoldingState } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel'; import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; @@ -295,7 +294,7 @@ export class StatefulMarkdownCell extends Disposable { const width = this.viewCell.layoutInfo.editorWidth; const lineNum = this.viewCell.lineCount; const lineHeight = this.viewCell.layoutInfo.fontInfo?.lineHeight || 17; - editorHeight = Math.max(lineNum, 1) * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING; + editorHeight = Math.max(lineNum, 1) * lineHeight + getEditorTopPadding() + this.notebookEditor.notebookOptions.getLayoutConfiguration().editorBottomPadding; this.templateData.editorContainer.innerText = ''; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index 74b720ee021..196401b6441 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -12,12 +12,12 @@ import { IPosition } from 'vs/editor/common/core/position'; import * as editorCommon from 'vs/editor/common/editorCommon'; import * as model from 'vs/editor/common/model'; import { SearchParams } from 'vs/editor/common/model/textModelSearch'; -import { CELL_STATUSBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants'; import { CellEditState, CellFocusMode, CursorAtBoundary, CellViewModelStateChangeEvent, IEditableCellViewModel, INotebookCellDecorationOptions, getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellKind, INotebookSearchOptions, ShowCellStatusBarKey, INotebookCellStatusBarItem } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService'; +import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; export abstract class BaseCellViewModel extends Disposable { @@ -129,6 +129,7 @@ export abstract class BaseCellViewModel extends Disposable { readonly viewType: string, readonly model: NotebookCellTextModel, public id: string, + private readonly _eventDispatcher: NotebookEventDispatcher, private readonly _configurationService: IConfigurationService, private readonly _modelService: ITextModelService, ) { @@ -151,7 +152,7 @@ export abstract class BaseCellViewModel extends Disposable { getEditorStatusbarHeight() { const showCellStatusBar = this._configurationService.getValue(ShowCellStatusBarKey); - return showCellStatusBar ? CELL_STATUSBAR_HEIGHT : 0; + return showCellStatusBar ? this._eventDispatcher.notebookOptions.getLayoutConfiguration().cellStatusBarHeight : 0; } abstract hasDynamicHeight(): boolean; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 0527dea30c0..2c61408cc87 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -9,7 +9,6 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_RIGHT_MARGIN, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants'; import { CellEditState, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo, CodeCellLayoutState, getEditorTopPadding, ICellOutputViewModel, ICellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; @@ -101,7 +100,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod @INotebookService private readonly _notebookService: INotebookService, @ITextModelService modelService: ITextModelService, ) { - super(viewType, model, UUID.generateUuid(), configurationService, modelService); + super(viewType, model, UUID.generateUuid(), eventDispatcher, configurationService, modelService); this._outputViewModels = this.model.outputs.map(output => new CellOutputViewModel(this, output, this._notebookService)); this._register(this.model.onDidChangeOutputs((splices) => { @@ -145,14 +144,18 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod } private computeEditorWidth(outerWidth: number): number { - return outerWidth - (CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER + CELL_RIGHT_MARGIN); + return outerWidth - ( + this.eventDispatcher.notebookOptions.getLayoutConfiguration().codeCellLeftMargin // CODE_CELL_LEFT_MARGIN + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellRunGutter // CELL_RUN_GUTTER + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellRightMargin // CELL_RIGHT_MARGIN + ); } layoutChange(state: CodeCellLayoutChangeEvent, source?: string) { // recompute this._ensureOutputsTop(); const outputShowMoreContainerHeight = state.outputShowMoreContainerHeight ? state.outputShowMoreContainerHeight : this._layoutInfo.outputShowMoreContainerHeight; - let outputTotalHeight = Math.max(this._outputMinHeight, this.metadata?.outputCollapsed ? COLLAPSED_INDICATOR_HEIGHT : this._outputsTop!.getTotalValue()); + let outputTotalHeight = Math.max(this._outputMinHeight, this.metadata?.outputCollapsed ? this.eventDispatcher.notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight : this._outputsTop!.getTotalValue()); if (!this.metadata?.inputCollapsed) { let newState: CodeCellLayoutState; @@ -176,9 +179,17 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod const statusbarHeight = this.getEditorStatusbarHeight(); const indicatorHeight = editorHeight + statusbarHeight + outputTotalHeight + outputShowMoreContainerHeight; - const outputContainerOffset = EDITOR_TOOLBAR_HEIGHT + CELL_TOP_MARGIN + editorHeight + statusbarHeight; - const outputShowMoreContainerOffset = totalHeight - BOTTOM_CELL_TOOLBAR_GAP - BOTTOM_CELL_TOOLBAR_HEIGHT / 2 - outputShowMoreContainerHeight; - const bottomToolbarOffset = totalHeight - BOTTOM_CELL_TOOLBAR_GAP - BOTTOM_CELL_TOOLBAR_HEIGHT / 2; + const outputContainerOffset = this.eventDispatcher.notebookOptions.getLayoutConfiguration().editorToolbarHeight + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellTopMargin // CELL_TOP_MARGIN + + editorHeight + + statusbarHeight; + const outputShowMoreContainerOffset = totalHeight + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight / 2 + - outputShowMoreContainerHeight; + const bottomToolbarOffset = totalHeight + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight / 2; const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth; this._layoutInfo = { @@ -196,11 +207,22 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod }; } else { outputTotalHeight = Math.max(this._outputMinHeight, this.metadata?.inputCollapsed && this.metadata.outputCollapsed ? 0 : outputTotalHeight); - const indicatorHeight = COLLAPSED_INDICATOR_HEIGHT + outputTotalHeight + outputShowMoreContainerHeight; - const outputContainerOffset = CELL_TOP_MARGIN + COLLAPSED_INDICATOR_HEIGHT; - const totalHeight = CELL_TOP_MARGIN + COLLAPSED_INDICATOR_HEIGHT + CELL_BOTTOM_MARGIN + BOTTOM_CELL_TOOLBAR_GAP + outputTotalHeight + outputShowMoreContainerHeight; - const outputShowMoreContainerOffset = totalHeight - BOTTOM_CELL_TOOLBAR_GAP - BOTTOM_CELL_TOOLBAR_HEIGHT / 2 - outputShowMoreContainerHeight; - const bottomToolbarOffset = totalHeight - BOTTOM_CELL_TOOLBAR_GAP - BOTTOM_CELL_TOOLBAR_HEIGHT / 2; + const indicatorHeight = this.eventDispatcher.notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight + outputTotalHeight + outputShowMoreContainerHeight; + + const outputContainerOffset = this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellTopMargin + this.eventDispatcher.notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight; + const totalHeight = + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellTopMargin + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellBottomMargin //CELL_BOTTOM_MARGIN + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap //BOTTOM_CELL_TOOLBAR_GAP + + outputTotalHeight + outputShowMoreContainerHeight; + const outputShowMoreContainerOffset = totalHeight + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight / 2 + - outputShowMoreContainerHeight; + const bottomToolbarOffset = totalHeight + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight / 2; const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth; this._layoutInfo = { @@ -282,11 +304,21 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod } const verticalScrollbarHeight = hasScrolling ? 12 : 0; // take zoom level into account - return this.lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING + verticalScrollbarHeight; + return this.lineCount * lineHeight + + getEditorTopPadding() + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().editorBottomPadding // EDITOR_BOTTOM_PADDING + + verticalScrollbarHeight; } private computeTotalHeight(editorHeight: number, outputsTotalHeight: number, outputShowMoreContainerHeight: number): number { - return EDITOR_TOOLBAR_HEIGHT + CELL_TOP_MARGIN + editorHeight + this.getEditorStatusbarHeight() + outputsTotalHeight + outputShowMoreContainerHeight + BOTTOM_CELL_TOOLBAR_GAP + CELL_BOTTOM_MARGIN; + return this.eventDispatcher.notebookOptions.getLayoutConfiguration().editorToolbarHeight //EDITOR_TOOLBAR_HEIGHT + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellTopMargin // CELL_TOP_MARGIN + + editorHeight + + this.getEditorStatusbarHeight() + + outputsTotalHeight + + outputShowMoreContainerHeight + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap //BOTTOM_CELL_TOOLBAR_GAP + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellBottomMargin; // CELL_BOTTOM_MARGIN; } protected onDidChangeTextModelContent(): void { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher.ts index c20c60d81a0..eda60b804f8 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher.ts @@ -6,6 +6,7 @@ import { Emitter } from 'vs/base/common/event'; import { NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookLayoutChangeEvent, NotebookLayoutInfo, CellViewModelStateChangeEvent, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; export enum NotebookViewEventType { LayoutChanged = 1, @@ -49,7 +50,7 @@ export class NotebookEventDispatcher { protected readonly _onDidChangeCellState = new Emitter(); readonly onDidChangeCellState = this._onDidChangeCellState.event; - constructor() { + constructor(readonly notebookOptions: NotebookOptions) { } emit(events: NotebookViewEvent[]) { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index 17b3583204c..504cd72618c 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -8,7 +8,6 @@ import * as UUID from 'vs/base/common/uuid'; import * as editorCommon from 'vs/editor/common/editorCommon'; import * as nls from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, MARKDOWN_CELL_BOTTOM_MARGIN, MARKDOWN_CELL_TOP_MARGIN, CELL_RIGHT_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants'; import { EditorFoldingStateDelegate } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel'; import { CellEditState, CellFindMatch, ICellOutputViewModel, ICellViewModel, MarkdownCellLayoutChangeEvent, MarkdownCellLayoutInfo, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer'; @@ -29,7 +28,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie set renderedMarkdownHeight(newHeight: number) { if (this.getEditState() === CellEditState.Preview) { - const newTotalHeight = newHeight + BOTTOM_CELL_TOOLBAR_GAP; + const newTotalHeight = newHeight + this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap; // BOTTOM_CELL_TOOLBAR_GAP; this.totalHeight = newTotalHeight; } } @@ -48,7 +47,11 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie set editorHeight(newHeight: number) { this._editorHeight = newHeight; - this.totalHeight = this._editorHeight + MARKDOWN_CELL_TOP_MARGIN + MARKDOWN_CELL_BOTTOM_MARGIN + BOTTOM_CELL_TOOLBAR_GAP + this.getEditorStatusbarHeight(); + this.totalHeight = this._editorHeight + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().markdownCellBottomMargin // MARKDOWN_CELL_BOTTOM_MARGIN + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP + + this.getEditorStatusbarHeight(); } get editorHeight() { @@ -107,13 +110,13 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie @IConfigurationService configurationService: IConfigurationService, @ITextModelService textModelService: ITextModelService, ) { - super(viewType, model, UUID.generateUuid(), configurationService, textModelService); + super(viewType, model, UUID.generateUuid(), eventDispatcher, configurationService, textModelService); this._layoutInfo = { editorHeight: 0, fontInfo: initialNotebookLayoutInfo?.fontInfo || null, editorWidth: initialNotebookLayoutInfo?.width ? this.computeEditorWidth(initialNotebookLayoutInfo.width) : 0, - bottomToolbarOffset: BOTTOM_CELL_TOOLBAR_GAP, + bottomToolbarOffset: this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap, // BOTTOM_CELL_TOOLBAR_GAP, totalHeight: 0 }; @@ -145,7 +148,9 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie } private computeEditorWidth(outerWidth: number) { - return outerWidth - CODE_CELL_LEFT_MARGIN - CELL_RIGHT_MARGIN; + return outerWidth + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().codeCellLeftMargin // CODE_CELL_LEFT_MARGIN + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellRightMargin; // CELL_RIGHT_MARGIN; } layoutChange(state: MarkdownCellLayoutChangeEvent) { @@ -159,19 +164,28 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie fontInfo: state.font || this._layoutInfo.fontInfo, editorWidth, editorHeight: this._editorHeight, - bottomToolbarOffset: totalHeight - BOTTOM_CELL_TOOLBAR_GAP - BOTTOM_CELL_TOOLBAR_HEIGHT / 2, + bottomToolbarOffset: totalHeight + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap /* BOTTOM_CELL_TOOLBAR_GAP */ + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight /* BOTTOM_CELL_TOOLBAR_HEIGHT */ / 2, totalHeight }; } else { const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth; - const totalHeight = MARKDOWN_CELL_TOP_MARGIN + COLLAPSED_INDICATOR_HEIGHT + BOTTOM_CELL_TOOLBAR_GAP + MARKDOWN_CELL_BOTTOM_MARGIN; + const totalHeight = + this.eventDispatcher.notebookOptions.getLayoutConfiguration().markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight // COLLAPSED_INDICATOR_HEIGHT + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP + + this.eventDispatcher.notebookOptions.getLayoutConfiguration().markdownCellBottomMargin; // MARKDOWN_CELL_BOTTOM_MARGIN; + state.totalHeight = totalHeight; this._layoutInfo = { fontInfo: state.font || this._layoutInfo.fontInfo, editorWidth, editorHeight: this._editorHeight, - bottomToolbarOffset: totalHeight - BOTTOM_CELL_TOOLBAR_GAP - BOTTOM_CELL_TOOLBAR_HEIGHT / 2, + bottomToolbarOffset: totalHeight + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP + - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight / 2, totalHeight }; } diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index c0bed227d91..8207d1a691e 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -888,3 +888,22 @@ export class NotebookWorkingCopyTypeIdentifier { return undefined; } } + +export interface NotebookLayoutConfiguration { + cellRightMargin: number, + cellRunGutter: number, + cellStatusBarHeight: number, + cellTopMargin: number, + cellBottomMargin: number, + cellOutputPadding: number, + codeCellLeftMargin: number, + markdownCellTopMargin: number, + markdownCellBottomMargin: number, + markdownPreviewPadding: number, + bottomCellToolbarGap: number, + bottomCellToolbarHeight: number, + editorToolbarHeight: number, + editorBottomPadding: number, + editorBottomPaddingWithoutStatusBar: number, + collapsedIndicatorHeight: number, +} diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts new file mode 100644 index 00000000000..8bc018f033e --- /dev/null +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -0,0 +1,56 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { NotebookLayoutConfiguration } from 'vs/workbench/contrib/notebook/common/notebookCommon'; + +const CELL_STATUSBAR_HEIGHT = 22; +const EDITOR_TOOLBAR_HEIGHT = 0; +const CELL_OUTPUT_PADDING = 14; +const MARKDOWN_PREVIEW_PADDING = 8; +const CELL_RIGHT_MARGIN = 16; +const CELL_RUN_GUTTER = 28; +const CODE_CELL_LEFT_MARGIN = 32; +const BOTTOM_CELL_TOOLBAR_GAP = 18; +const BOTTOM_CELL_TOOLBAR_HEIGHT = 22; + +// Margin above editor +const CELL_TOP_MARGIN = 6; +const CELL_BOTTOM_MARGIN = 6; + +const MARKDOWN_CELL_TOP_MARGIN = 8; +const MARKDOWN_CELL_BOTTOM_MARGIN = 8; + +const COLLAPSED_INDICATOR_HEIGHT = 24; +const EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR = 12; +const EDITOR_BOTTOM_PADDING = 4; + +export class NotebookOptions { + private _layoutConfiguration: NotebookLayoutConfiguration; + + constructor() { + this._layoutConfiguration = { + cellRightMargin: CELL_RIGHT_MARGIN, + cellRunGutter: CELL_RUN_GUTTER, + cellStatusBarHeight: CELL_STATUSBAR_HEIGHT, + cellTopMargin: CELL_TOP_MARGIN, + cellBottomMargin: CELL_BOTTOM_MARGIN, + codeCellLeftMargin: CODE_CELL_LEFT_MARGIN, + markdownCellTopMargin: MARKDOWN_CELL_TOP_MARGIN, + markdownCellBottomMargin: MARKDOWN_CELL_BOTTOM_MARGIN, + bottomCellToolbarGap: BOTTOM_CELL_TOOLBAR_GAP, + bottomCellToolbarHeight: BOTTOM_CELL_TOOLBAR_HEIGHT, + editorBottomPadding: EDITOR_BOTTOM_PADDING, + editorBottomPaddingWithoutStatusBar: EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR, + editorToolbarHeight: EDITOR_TOOLBAR_HEIGHT, + cellOutputPadding: CELL_OUTPUT_PADDING, + collapsedIndicatorHeight: COLLAPSED_INDICATOR_HEIGHT, + markdownPreviewPadding: MARKDOWN_PREVIEW_PADDING + }; + } + + getLayoutConfiguration(): NotebookLayoutConfiguration { + return this._layoutConfiguration; + } +} diff --git a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts index 91515c0c385..a0c9fd65a35 100644 --- a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts +++ b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts @@ -20,6 +20,7 @@ import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/v import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { CellKind, diff, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import { NotebookEditorTestModel, setupInstantiationService, withTestNotebook } from 'vs/workbench/contrib/notebook/test/testNotebookEditor'; @@ -37,7 +38,7 @@ suite('NotebookViewModel', () => { test('ctor', function () { const notebook = new NotebookTextModel('notebook', URI.parse('test'), [], notebookDocumentMetadataDefaults, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false }, undoRedoService, modelService, modeService); const model = new NotebookEditorTestModel(notebook); - const eventDispatcher = new NotebookEventDispatcher(); + const eventDispatcher = new NotebookEventDispatcher(new NotebookOptions()); const viewModel = new NotebookViewModel('notebook', model.notebook, eventDispatcher, null, instantiationService, bulkEditService, undoRedoService, textModelService); assert.strictEqual(viewModel.viewType, 'notebook'); }); diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index 20460f430cd..c19601ab84f 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -42,6 +42,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage'; import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust'; import { TestWorkspaceTrustRequestService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService'; +import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; export class TestCell extends NotebookCellTextModel { constructor( @@ -171,7 +172,7 @@ function _createTestNotebookEditor(instantiationService: TestInstantiationServic }), notebookDocumentMetadataDefaults, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false }); const model = new NotebookEditorTestModel(notebook); - const eventDispatcher = new NotebookEventDispatcher(); + const eventDispatcher = new NotebookEventDispatcher(new NotebookOptions()); const viewModel: NotebookViewModel = instantiationService.createInstance(NotebookViewModel, viewType, model.notebook, eventDispatcher, null); const cellList = createNotebookCellList(instantiationService); From 55888553df9609e3746f9feee54d92518439f98c Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 13:40:01 -0700 Subject: [PATCH 03/76] use stylesheet text content other than insertRule as the DOM node might not be attached yet. --- .../notebook/browser/notebookEditorWidget.ts | 69 ++++++++----------- 1 file changed, 30 insertions(+), 39 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 7ba96f5e66b..988905bf58e 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -204,6 +204,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private _overlayContainer!: HTMLElement; private _notebookTopToolbarContainer!: HTMLElement; private _body!: HTMLElement; + private _styleElement!: HTMLStyleElement; private _overflowContainer!: HTMLElement; private _webview: BackLayerWebView | null = null; private _webviewResolvePromise: Promise | null> | null = null; @@ -565,20 +566,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } private _createLayoutStyles(): void { - const styleElement = DOM.createStyleSheet(this._body); - const styleSheet = new NotebookRefCountedStyleSheet({ - removeEditorStyleSheets: (key) => { - // this._editorStyleSheets.delete(key); - if (key === 'notebook-layout-styles') { - if (styleElement && styleElement.parentElement) { - styleElement.parentElement.removeChild(styleElement); - } - } - } - }, 'notebook-layout-style', styleElement); - styleSheet.ref(); - // Cell Margin - + this._styleElement = DOM.createStyleSheet(this._body); const cellRightMargin = this._notebookOptions.getLayoutConfiguration().cellRightMargin; const cellTopMargin = this._notebookOptions.getLayoutConfiguration().cellTopMargin; const cellRunGutter = this._notebookOptions.getLayoutConfiguration().cellRunGutter; @@ -589,44 +577,47 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const bottomCellToolbarGap = this._notebookOptions.getLayoutConfiguration().bottomCellToolbarGap; const bottomCellToolbarHeight = this._notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight; const collapsedIndicatorHeight = this._notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight; - styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row div.cell.code { margin-left: ${codeCellLeftMargin}px; }`); - styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .code-cell-row div.cell.code { margin-left: ${codeCellLeftMargin + cellRunGutter}px; }`); - styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell { margin-right: ${cellRightMargin}px; }`); - styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > .cell-inner-container { padding-top: ${cellTopMargin}px; }`); - styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container { padding-bottom: ${markdownCellBottomMargin}px; padding-top: ${markdownCellTopMargin}px; }`); - styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container.webview-backed-markdown-cell { padding: 0; }`); - styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .webview-backed-markdown-cell.markdown-cell-edit-mode .cell.code { padding-bottom: ${markdownCellBottomMargin}px; padding-top: ${markdownCellTopMargin}px; }`); - styleSheet.insertRule(`.notebookOverlay .output { margin: 0px ${cellRightMargin}px 0px ${codeCellLeftMargin + cellRunGutter}px; }`); - styleSheet.insertRule(`.notebookOverlay .output { width: calc(100% - ${codeCellLeftMargin + cellRunGutter + cellRightMargin}px); }`); + const styleSheets: string[] = []; + styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row div.cell.code { margin-left: ${codeCellLeftMargin}px; }`); + styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .code-cell-row div.cell.code { margin-left: ${codeCellLeftMargin + cellRunGutter}px; }`); + styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell { margin-right: ${cellRightMargin}px; }`); + styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > .cell-inner-container { padding-top: ${cellTopMargin}px; }`); + styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container { padding-bottom: ${markdownCellBottomMargin}px; padding-top: ${markdownCellTopMargin}px; }`); + styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container.webview-backed-markdown-cell { padding: 0; }`); + styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .webview-backed-markdown-cell.markdown-cell-edit-mode .cell.code { padding-bottom: ${markdownCellBottomMargin}px; padding-top: ${markdownCellTopMargin}px; }`); + styleSheets.push(`.notebookOverlay .output { margin: 0px ${cellRightMargin}px 0px ${codeCellLeftMargin + cellRunGutter}px; }`); + styleSheets.push(`.notebookOverlay .output { width: calc(100% - ${codeCellLeftMargin + cellRunGutter + cellRightMargin}px); }`); - styleSheet.insertRule(`.notebookOverlay .output-show-more-container { margin: 0px ${cellRightMargin}px 0px ${codeCellLeftMargin + cellRunGutter}px; }`); - styleSheet.insertRule(`.notebookOverlay .output-show-more-container { width: calc(100% - ${codeCellLeftMargin + cellRunGutter + cellRightMargin}px); }`); + styleSheets.push(`.notebookOverlay .output-show-more-container { margin: 0px ${cellRightMargin}px 0px ${codeCellLeftMargin + cellRunGutter}px; }`); + styleSheets.push(`.notebookOverlay .output-show-more-container { width: calc(100% - ${codeCellLeftMargin + cellRunGutter + cellRightMargin}px); }`); - styleSheet.insertRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell.markdown { padding-left: ${cellRunGutter}px; }`); - styleSheet.insertRule(`.notebookOverlay .cell .run-button-container { width: 20px; left: ${codeCellLeftMargin + Math.floor(cellRunGutter - 20) / 2}px }`); - styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row :not(.webview-backed-markdown-cell) .cell-focus-indicator-top { height: ${cellTopMargin}px; }`); - styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { bottom: ${bottomCellToolbarGap}px; }`); - styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-focus-indicator-left, + styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell.markdown { padding-left: ${cellRunGutter}px; }`); + styleSheets.push(`.notebookOverlay .cell .run-button-container { width: 20px; left: ${codeCellLeftMargin + Math.floor(cellRunGutter - 20) / 2}px }`); + styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row :not(.webview-backed-markdown-cell) .cell-focus-indicator-top { height: ${cellTopMargin}px; }`); + styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { bottom: ${bottomCellToolbarGap}px; }`); + styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-focus-indicator-left, .notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-drag-handle { width: ${codeCellLeftMargin + cellRunGutter}px; }`); - styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row .cell-focus-indicator-left { width: ${codeCellLeftMargin}px; }`); - styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator.cell-focus-indicator-right { width: ${cellRightMargin}px; }`); - styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-bottom { height: ${cellBottomMargin}px; }`); - styleSheet.insertRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-shadow-container-bottom { top: ${cellBottomMargin}px; }`); + styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row .cell-focus-indicator-left { width: ${codeCellLeftMargin}px; }`); + styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator.cell-focus-indicator-right { width: ${cellRightMargin}px; }`); + styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-bottom { height: ${cellBottomMargin}px; }`); + styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-shadow-container-bottom { top: ${cellBottomMargin}px; }`); - styleSheet.insertRule(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-collapsed-part { margin-left: ${codeCellLeftMargin + cellRunGutter}px; height: ${collapsedIndicatorHeight}px; }`); - styleSheet.insertRule(`.notebookOverlay .cell-list-top-cell-toolbar-container { top: -${SCROLLABLE_ELEMENT_PADDING_TOP}px }`); + styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-collapsed-part { margin-left: ${codeCellLeftMargin + cellRunGutter}px; height: ${collapsedIndicatorHeight}px; }`); + styleSheets.push(`.notebookOverlay .cell-list-top-cell-toolbar-container { top: -${SCROLLABLE_ELEMENT_PADDING_TOP}px }`); - styleSheet.insertRule(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container { height: ${bottomCellToolbarHeight}px }`); - styleSheet.insertRule(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .cell-list-top-cell-toolbar-container { height: ${bottomCellToolbarHeight}px }`); + styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container { height: ${bottomCellToolbarHeight}px }`); + styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .cell-list-top-cell-toolbar-container { height: ${bottomCellToolbarHeight}px }`); // left and right border margins - styleSheet.insertRule(` + styleSheets.push(` .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.focused .cell-focus-indicator-left:before, .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.focused .cell-focus-indicator-right:before, .monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-left:before, .monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-right:before { top: -${cellTopMargin}px; height: calc(100% + ${cellTopMargin + cellBottomMargin}px) }`); + + this._styleElement.textContent = styleSheets.join('\n'); } private _createCellList(): void { From 65aa0c2630a9e5a0b13dad8d84ccd45605d59380 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 13:53:13 -0700 Subject: [PATCH 04/76] :lipstick: --- .../notebook/browser/notebookEditorWidget.ts | 23 ++++---- .../browser/viewModel/codeCellViewModel.ts | 52 ++++++++++--------- .../viewModel/markdownCellViewModel.ts | 30 ++++++----- .../contrib/notebook/common/notebookCommon.ts | 18 ------- .../notebook/common/notebookOptions.ts | 21 +++++++- 5 files changed, 77 insertions(+), 67 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 988905bf58e..12566279084 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -567,16 +567,19 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private _createLayoutStyles(): void { this._styleElement = DOM.createStyleSheet(this._body); - const cellRightMargin = this._notebookOptions.getLayoutConfiguration().cellRightMargin; - const cellTopMargin = this._notebookOptions.getLayoutConfiguration().cellTopMargin; - const cellRunGutter = this._notebookOptions.getLayoutConfiguration().cellRunGutter; - const cellBottomMargin = this._notebookOptions.getLayoutConfiguration().cellBottomMargin; - const codeCellLeftMargin = this._notebookOptions.getLayoutConfiguration().codeCellLeftMargin; - const markdownCellBottomMargin = this._notebookOptions.getLayoutConfiguration().markdownCellBottomMargin; - const markdownCellTopMargin = this._notebookOptions.getLayoutConfiguration().markdownCellTopMargin; - const bottomCellToolbarGap = this._notebookOptions.getLayoutConfiguration().bottomCellToolbarGap; - const bottomCellToolbarHeight = this._notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight; - const collapsedIndicatorHeight = this._notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight; + const { + cellRightMargin, + cellTopMargin, + cellRunGutter, + cellBottomMargin, + codeCellLeftMargin, + markdownCellBottomMargin, + markdownCellTopMargin, + bottomCellToolbarGap, + bottomCellToolbarHeight, + collapsedIndicatorHeight + } = this._notebookOptions.getLayoutConfiguration(); + const styleSheets: string[] = []; styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row div.cell.code { margin-left: ${codeCellLeftMargin}px; }`); styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .code-cell-row div.cell.code { margin-left: ${codeCellLeftMargin + cellRunGutter}px; }`); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 2c61408cc87..6ac2d0716b5 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -144,18 +144,21 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod } private computeEditorWidth(outerWidth: number): number { + const notebookLayoutConfiguration = this.eventDispatcher.notebookOptions.getLayoutConfiguration(); + return outerWidth - ( - this.eventDispatcher.notebookOptions.getLayoutConfiguration().codeCellLeftMargin // CODE_CELL_LEFT_MARGIN - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellRunGutter // CELL_RUN_GUTTER - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellRightMargin // CELL_RIGHT_MARGIN + notebookLayoutConfiguration.codeCellLeftMargin // CODE_CELL_LEFT_MARGIN + + notebookLayoutConfiguration.cellRunGutter // CELL_RUN_GUTTER + + notebookLayoutConfiguration.cellRightMargin // CELL_RIGHT_MARGIN ); } layoutChange(state: CodeCellLayoutChangeEvent, source?: string) { // recompute this._ensureOutputsTop(); + const notebookLayoutConfiguration = this.eventDispatcher.notebookOptions.getLayoutConfiguration(); const outputShowMoreContainerHeight = state.outputShowMoreContainerHeight ? state.outputShowMoreContainerHeight : this._layoutInfo.outputShowMoreContainerHeight; - let outputTotalHeight = Math.max(this._outputMinHeight, this.metadata?.outputCollapsed ? this.eventDispatcher.notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight : this._outputsTop!.getTotalValue()); + let outputTotalHeight = Math.max(this._outputMinHeight, this.metadata?.outputCollapsed ? notebookLayoutConfiguration.collapsedIndicatorHeight : this._outputsTop!.getTotalValue()); if (!this.metadata?.inputCollapsed) { let newState: CodeCellLayoutState; @@ -179,17 +182,17 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod const statusbarHeight = this.getEditorStatusbarHeight(); const indicatorHeight = editorHeight + statusbarHeight + outputTotalHeight + outputShowMoreContainerHeight; - const outputContainerOffset = this.eventDispatcher.notebookOptions.getLayoutConfiguration().editorToolbarHeight - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellTopMargin // CELL_TOP_MARGIN + const outputContainerOffset = notebookLayoutConfiguration.editorToolbarHeight + + notebookLayoutConfiguration.cellTopMargin // CELL_TOP_MARGIN + editorHeight + statusbarHeight; const outputShowMoreContainerOffset = totalHeight - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight / 2 + - notebookLayoutConfiguration.bottomCellToolbarGap + - notebookLayoutConfiguration.bottomCellToolbarHeight / 2 - outputShowMoreContainerHeight; const bottomToolbarOffset = totalHeight - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight / 2; + - notebookLayoutConfiguration.bottomCellToolbarGap + - notebookLayoutConfiguration.bottomCellToolbarHeight / 2; const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth; this._layoutInfo = { @@ -207,22 +210,22 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod }; } else { outputTotalHeight = Math.max(this._outputMinHeight, this.metadata?.inputCollapsed && this.metadata.outputCollapsed ? 0 : outputTotalHeight); - const indicatorHeight = this.eventDispatcher.notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight + outputTotalHeight + outputShowMoreContainerHeight; + const indicatorHeight = notebookLayoutConfiguration.collapsedIndicatorHeight + outputTotalHeight + outputShowMoreContainerHeight; - const outputContainerOffset = this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellTopMargin + this.eventDispatcher.notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight; + const outputContainerOffset = notebookLayoutConfiguration.cellTopMargin + notebookLayoutConfiguration.collapsedIndicatorHeight; const totalHeight = - this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellTopMargin - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellBottomMargin //CELL_BOTTOM_MARGIN - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap //BOTTOM_CELL_TOOLBAR_GAP + notebookLayoutConfiguration.cellTopMargin + + notebookLayoutConfiguration.collapsedIndicatorHeight + + notebookLayoutConfiguration.cellBottomMargin //CELL_BOTTOM_MARGIN + + notebookLayoutConfiguration.bottomCellToolbarGap //BOTTOM_CELL_TOOLBAR_GAP + outputTotalHeight + outputShowMoreContainerHeight; const outputShowMoreContainerOffset = totalHeight - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight / 2 + - notebookLayoutConfiguration.bottomCellToolbarGap + - notebookLayoutConfiguration.bottomCellToolbarHeight / 2 - outputShowMoreContainerHeight; const bottomToolbarOffset = totalHeight - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight / 2; + - notebookLayoutConfiguration.bottomCellToolbarGap + - notebookLayoutConfiguration.bottomCellToolbarHeight / 2; const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth; this._layoutInfo = { @@ -311,14 +314,15 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod } private computeTotalHeight(editorHeight: number, outputsTotalHeight: number, outputShowMoreContainerHeight: number): number { - return this.eventDispatcher.notebookOptions.getLayoutConfiguration().editorToolbarHeight //EDITOR_TOOLBAR_HEIGHT - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellTopMargin // CELL_TOP_MARGIN + const layoutConfiguration = this.eventDispatcher.notebookOptions.getLayoutConfiguration(); + return layoutConfiguration.editorToolbarHeight //EDITOR_TOOLBAR_HEIGHT + + layoutConfiguration.cellTopMargin // CELL_TOP_MARGIN + editorHeight + this.getEditorStatusbarHeight() + outputsTotalHeight + outputShowMoreContainerHeight - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap //BOTTOM_CELL_TOOLBAR_GAP - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellBottomMargin; // CELL_BOTTOM_MARGIN; + + layoutConfiguration.bottomCellToolbarGap //BOTTOM_CELL_TOOLBAR_GAP + + layoutConfiguration.cellBottomMargin; // CELL_BOTTOM_MARGIN; } protected onDidChangeTextModelContent(): void { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index 504cd72618c..c8ad7327f50 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -46,11 +46,12 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie private _editorHeight = 0; set editorHeight(newHeight: number) { this._editorHeight = newHeight; + const layoutConfiguration = this.eventDispatcher.notebookOptions.getLayoutConfiguration(); this.totalHeight = this._editorHeight - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().markdownCellBottomMargin // MARKDOWN_CELL_BOTTOM_MARGIN - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP + + layoutConfiguration.markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN + + layoutConfiguration.markdownCellBottomMargin // MARKDOWN_CELL_BOTTOM_MARGIN + + layoutConfiguration.bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP + this.getEditorStatusbarHeight(); } @@ -148,13 +149,16 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie } private computeEditorWidth(outerWidth: number) { + const notebookLayoutConfiguration = this.eventDispatcher.notebookOptions.getLayoutConfiguration(); + return outerWidth - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().codeCellLeftMargin // CODE_CELL_LEFT_MARGIN - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().cellRightMargin; // CELL_RIGHT_MARGIN; + - notebookLayoutConfiguration.codeCellLeftMargin // CODE_CELL_LEFT_MARGIN + - notebookLayoutConfiguration.cellRightMargin; // CELL_RIGHT_MARGIN; } layoutChange(state: MarkdownCellLayoutChangeEvent) { // recompute + const notebookLayoutConfiguration = this.eventDispatcher.notebookOptions.getLayoutConfiguration(); if (!this.metadata?.inputCollapsed) { const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth; @@ -165,17 +169,17 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie editorWidth, editorHeight: this._editorHeight, bottomToolbarOffset: totalHeight - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap /* BOTTOM_CELL_TOOLBAR_GAP */ - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight /* BOTTOM_CELL_TOOLBAR_HEIGHT */ / 2, + - notebookLayoutConfiguration.bottomCellToolbarGap /* BOTTOM_CELL_TOOLBAR_GAP */ + - notebookLayoutConfiguration.bottomCellToolbarHeight /* BOTTOM_CELL_TOOLBAR_HEIGHT */ / 2, totalHeight }; } else { const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth; const totalHeight = - this.eventDispatcher.notebookOptions.getLayoutConfiguration().markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().collapsedIndicatorHeight // COLLAPSED_INDICATOR_HEIGHT - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().markdownCellBottomMargin; // MARKDOWN_CELL_BOTTOM_MARGIN; + notebookLayoutConfiguration.markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN + + notebookLayoutConfiguration.collapsedIndicatorHeight // COLLAPSED_INDICATOR_HEIGHT + + notebookLayoutConfiguration.bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP + + notebookLayoutConfiguration.markdownCellBottomMargin; // MARKDOWN_CELL_BOTTOM_MARGIN; state.totalHeight = totalHeight; @@ -184,8 +188,8 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie editorWidth, editorHeight: this._editorHeight, bottomToolbarOffset: totalHeight - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP - - this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarHeight / 2, + - notebookLayoutConfiguration.bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP + - notebookLayoutConfiguration.bottomCellToolbarHeight / 2, totalHeight }; } diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 8207d1a691e..e09f29c8652 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -889,21 +889,3 @@ export class NotebookWorkingCopyTypeIdentifier { } } -export interface NotebookLayoutConfiguration { - cellRightMargin: number, - cellRunGutter: number, - cellStatusBarHeight: number, - cellTopMargin: number, - cellBottomMargin: number, - cellOutputPadding: number, - codeCellLeftMargin: number, - markdownCellTopMargin: number, - markdownCellBottomMargin: number, - markdownPreviewPadding: number, - bottomCellToolbarGap: number, - bottomCellToolbarHeight: number, - editorToolbarHeight: number, - editorBottomPadding: number, - editorBottomPaddingWithoutStatusBar: number, - collapsedIndicatorHeight: number, -} diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 8bc018f033e..c3c1f9ea5e2 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { NotebookLayoutConfiguration } from 'vs/workbench/contrib/notebook/common/notebookCommon'; - const CELL_STATUSBAR_HEIGHT = 22; const EDITOR_TOOLBAR_HEIGHT = 0; const CELL_OUTPUT_PADDING = 14; @@ -26,6 +24,25 @@ const COLLAPSED_INDICATOR_HEIGHT = 24; const EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR = 12; const EDITOR_BOTTOM_PADDING = 4; +export interface NotebookLayoutConfiguration { + cellRightMargin: number, + cellRunGutter: number, + cellStatusBarHeight: number, + cellTopMargin: number, + cellBottomMargin: number, + cellOutputPadding: number, + codeCellLeftMargin: number, + markdownCellTopMargin: number, + markdownCellBottomMargin: number, + markdownPreviewPadding: number, + bottomCellToolbarGap: number, + bottomCellToolbarHeight: number, + editorToolbarHeight: number, + editorBottomPadding: number, + editorBottomPaddingWithoutStatusBar: number, + collapsedIndicatorHeight: number, +} + export class NotebookOptions { private _layoutConfiguration: NotebookLayoutConfiguration; From 28cc8e8aab0908e63813ba1da4ac9189a20408a9 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 14:07:30 -0700 Subject: [PATCH 05/76] extract common layout calculation code. --- .../browser/viewModel/codeCellViewModel.ts | 8 ++------ .../browser/viewModel/markdownCellViewModel.ts | 16 +++------------- .../contrib/notebook/common/notebookOptions.ts | 13 +++++++++++++ 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 6ac2d0716b5..6e752bfdc2e 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -190,9 +190,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod - notebookLayoutConfiguration.bottomCellToolbarGap - notebookLayoutConfiguration.bottomCellToolbarHeight / 2 - outputShowMoreContainerHeight; - const bottomToolbarOffset = totalHeight - - notebookLayoutConfiguration.bottomCellToolbarGap - - notebookLayoutConfiguration.bottomCellToolbarHeight / 2; + const bottomToolbarOffset = this.eventDispatcher.notebookOptions.computeBottomToolbarOffset(totalHeight); const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth; this._layoutInfo = { @@ -223,9 +221,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod - notebookLayoutConfiguration.bottomCellToolbarGap - notebookLayoutConfiguration.bottomCellToolbarHeight / 2 - outputShowMoreContainerHeight; - const bottomToolbarOffset = totalHeight - - notebookLayoutConfiguration.bottomCellToolbarGap - - notebookLayoutConfiguration.bottomCellToolbarHeight / 2; + const bottomToolbarOffset = this.eventDispatcher.notebookOptions.computeBottomToolbarOffset(totalHeight); const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth; this._layoutInfo = { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index c8ad7327f50..21dfb66a978 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -158,8 +158,6 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie layoutChange(state: MarkdownCellLayoutChangeEvent) { // recompute - const notebookLayoutConfiguration = this.eventDispatcher.notebookOptions.getLayoutConfiguration(); - if (!this.metadata?.inputCollapsed) { const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth; const totalHeight = state.totalHeight === undefined ? this._layoutInfo.totalHeight : state.totalHeight; @@ -168,18 +166,12 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie fontInfo: state.font || this._layoutInfo.fontInfo, editorWidth, editorHeight: this._editorHeight, - bottomToolbarOffset: totalHeight - - notebookLayoutConfiguration.bottomCellToolbarGap /* BOTTOM_CELL_TOOLBAR_GAP */ - - notebookLayoutConfiguration.bottomCellToolbarHeight /* BOTTOM_CELL_TOOLBAR_HEIGHT */ / 2, + bottomToolbarOffset: this.eventDispatcher.notebookOptions.computeBottomToolbarOffset(totalHeight), totalHeight }; } else { const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth; - const totalHeight = - notebookLayoutConfiguration.markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN - + notebookLayoutConfiguration.collapsedIndicatorHeight // COLLAPSED_INDICATOR_HEIGHT - + notebookLayoutConfiguration.bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP - + notebookLayoutConfiguration.markdownCellBottomMargin; // MARKDOWN_CELL_BOTTOM_MARGIN; + const totalHeight = this.eventDispatcher.notebookOptions.computeCollapsedMarkdownCellHeight(); state.totalHeight = totalHeight; @@ -187,9 +179,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie fontInfo: state.font || this._layoutInfo.fontInfo, editorWidth, editorHeight: this._editorHeight, - bottomToolbarOffset: totalHeight - - notebookLayoutConfiguration.bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP - - notebookLayoutConfiguration.bottomCellToolbarHeight / 2, + bottomToolbarOffset: this.eventDispatcher.notebookOptions.computeBottomToolbarOffset(totalHeight), totalHeight }; } diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index c3c1f9ea5e2..0f684a8ba41 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -70,4 +70,17 @@ export class NotebookOptions { getLayoutConfiguration(): NotebookLayoutConfiguration { return this._layoutConfiguration; } + + computeCollapsedMarkdownCellHeight(): number { + return this._layoutConfiguration.markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN + + this._layoutConfiguration.collapsedIndicatorHeight // COLLAPSED_INDICATOR_HEIGHT + + this._layoutConfiguration.bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP + + this._layoutConfiguration.markdownCellBottomMargin; // MARKDOWN_CELL_BOTTOM_MARGIN; + } + + computeBottomToolbarOffset(totalHeight: number) { + return totalHeight + - this._layoutConfiguration.bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP + - this._layoutConfiguration.bottomCellToolbarHeight / 2; + } } From 325253366209fd9c07c362739c6ef3b6ed653903 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 14:53:50 -0700 Subject: [PATCH 06/76] compute editor width. --- .../browser/viewModel/codeCellViewModel.ts | 22 ++++++++----------- .../viewModel/markdownCellViewModel.ts | 20 ++++++++--------- .../notebook/common/notebookOptions.ts | 14 ++++++++++++ 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 6e752bfdc2e..4a2b3fe9c12 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -131,7 +131,9 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod this._layoutInfo = { fontInfo: initialNotebookLayoutInfo?.fontInfo || null, editorHeight: 0, - editorWidth: initialNotebookLayoutInfo ? this.computeEditorWidth(initialNotebookLayoutInfo.width) : 0, + editorWidth: initialNotebookLayoutInfo + ? this.eventDispatcher.notebookOptions.computeCodeCellEditorWidth(initialNotebookLayoutInfo.width) + : 0, outputContainerOffset: 0, outputTotalHeight: 0, outputShowMoreContainerHeight: 0, @@ -143,16 +145,6 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod }; } - private computeEditorWidth(outerWidth: number): number { - const notebookLayoutConfiguration = this.eventDispatcher.notebookOptions.getLayoutConfiguration(); - - return outerWidth - ( - notebookLayoutConfiguration.codeCellLeftMargin // CODE_CELL_LEFT_MARGIN - + notebookLayoutConfiguration.cellRunGutter // CELL_RUN_GUTTER - + notebookLayoutConfiguration.cellRightMargin // CELL_RIGHT_MARGIN - ); - } - layoutChange(state: CodeCellLayoutChangeEvent, source?: string) { // recompute this._ensureOutputsTop(); @@ -191,7 +183,9 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod - notebookLayoutConfiguration.bottomCellToolbarHeight / 2 - outputShowMoreContainerHeight; const bottomToolbarOffset = this.eventDispatcher.notebookOptions.computeBottomToolbarOffset(totalHeight); - const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth; + const editorWidth = state.outerWidth !== undefined + ? this.eventDispatcher.notebookOptions.computeCodeCellEditorWidth(state.outerWidth) + : this._layoutInfo?.editorWidth; this._layoutInfo = { fontInfo: state.font ?? this._layoutInfo.fontInfo ?? null, @@ -222,7 +216,9 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod - notebookLayoutConfiguration.bottomCellToolbarHeight / 2 - outputShowMoreContainerHeight; const bottomToolbarOffset = this.eventDispatcher.notebookOptions.computeBottomToolbarOffset(totalHeight); - const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth; + const editorWidth = state.outerWidth !== undefined + ? this.eventDispatcher.notebookOptions.computeCodeCellEditorWidth(state.outerWidth) + : this._layoutInfo?.editorWidth; this._layoutInfo = { fontInfo: state.font ?? this._layoutInfo.fontInfo ?? null, diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index 21dfb66a978..cb55e7f3831 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -116,7 +116,9 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._layoutInfo = { editorHeight: 0, fontInfo: initialNotebookLayoutInfo?.fontInfo || null, - editorWidth: initialNotebookLayoutInfo?.width ? this.computeEditorWidth(initialNotebookLayoutInfo.width) : 0, + editorWidth: initialNotebookLayoutInfo?.width + ? this.eventDispatcher.notebookOptions.computeMarkdownCellEditorWidth(initialNotebookLayoutInfo.width) + : 0, bottomToolbarOffset: this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap, // BOTTOM_CELL_TOOLBAR_GAP, totalHeight: 0 }; @@ -148,18 +150,12 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._onDidChangeState.fire({ foldingStateChanged: true }); } - private computeEditorWidth(outerWidth: number) { - const notebookLayoutConfiguration = this.eventDispatcher.notebookOptions.getLayoutConfiguration(); - - return outerWidth - - notebookLayoutConfiguration.codeCellLeftMargin // CODE_CELL_LEFT_MARGIN - - notebookLayoutConfiguration.cellRightMargin; // CELL_RIGHT_MARGIN; - } - layoutChange(state: MarkdownCellLayoutChangeEvent) { // recompute if (!this.metadata?.inputCollapsed) { - const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth; + const editorWidth = state.outerWidth !== undefined + ? this.eventDispatcher.notebookOptions.computeMarkdownCellEditorWidth(state.outerWidth) + : this._layoutInfo.editorWidth; const totalHeight = state.totalHeight === undefined ? this._layoutInfo.totalHeight : state.totalHeight; this._layoutInfo = { @@ -170,7 +166,9 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie totalHeight }; } else { - const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth; + const editorWidth = state.outerWidth !== undefined + ? this.eventDispatcher.notebookOptions.computeMarkdownCellEditorWidth(state.outerWidth) + : this._layoutInfo.editorWidth; const totalHeight = this.eventDispatcher.notebookOptions.computeCollapsedMarkdownCellHeight(); state.totalHeight = totalHeight; diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 0f684a8ba41..a7f3c6cd928 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -83,4 +83,18 @@ export class NotebookOptions { - this._layoutConfiguration.bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP - this._layoutConfiguration.bottomCellToolbarHeight / 2; } + + computeCodeCellEditorWidth(outerWidth: number): number { + return outerWidth - ( + this._layoutConfiguration.codeCellLeftMargin // CODE_CELL_LEFT_MARGIN + + this._layoutConfiguration.cellRunGutter // CELL_RUN_GUTTER + + this._layoutConfiguration.cellRightMargin // CELL_RIGHT_MARGIN + ); + } + + computeMarkdownCellEditorWidth(outerWidth: number): number { + return outerWidth + - this._layoutConfiguration.codeCellLeftMargin // CODE_CELL_LEFT_MARGIN + - this._layoutConfiguration.cellRightMargin; // CELL_RIGHT_MARGIN; + } } From 04398f16e8008934204d3ba65cfbb80c73e1c3d3 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 16:14:25 -0700 Subject: [PATCH 07/76] ViewContext for notebook options and event dispatcher. --- .../browser/diff/notebookTextDiffEditor.ts | 3 +- .../notebook/browser/notebookEditorWidget.ts | 10 ++-- .../browser/viewModel/baseCellViewModel.ts | 6 +- .../browser/viewModel/codeCellViewModel.ts | 22 +++---- .../browser/viewModel/eventDispatcher.ts | 3 +- .../viewModel/markdownCellViewModel.ts | 27 ++++----- .../browser/viewModel/notebookViewModel.ts | 13 +++-- .../notebook/browser/viewModel/viewContext.ts | 15 +++++ .../notebook/common/notebookOptions.ts | 57 ++++++++++++------- .../notebook/test/notebookViewModel.test.ts | 5 +- .../notebook/test/testNotebookEditor.ts | 5 +- 11 files changed, 103 insertions(+), 63 deletions(-) create mode 100644 src/vs/workbench/contrib/notebook/browser/viewModel/viewContext.ts diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 2b75f4f1716..d6c16589001 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -75,7 +75,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD protected _onDidDynamicOutputRendered = new Emitter<{ cell: IGenericCellViewModel, output: ICellOutputViewModel }>(); onDidDynamicOutputRendered = this._onDidDynamicOutputRendered.event; - private _notebookOptions = new NotebookOptions(); + private _notebookOptions: NotebookOptions; get notebookOptions() { return this._notebookOptions; @@ -99,6 +99,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD @IStorageService storageService: IStorageService, ) { super(NotebookTextDiffEditor.ID, telemetryService, themeService, storageService); + this._notebookOptions = new NotebookOptions(this.configurationService); const editorOptions = this.configurationService.getValue('editor'); this._fontInfo = readFontInfo(BareFontInfo.createFromRawSettings(editorOptions, getZoomLevel(), getPixelRatio())); this._revealFirst = true; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 12566279084..04bede842fa 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -76,6 +76,7 @@ import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/not import { NotebookEditorContextKeys } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidgetContextKeys'; import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; import { SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants'; +import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext'; const $ = DOM.$; @@ -215,6 +216,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private _dndController: CellDragAndDropController | null = null; private _listTopCellToolbar: ListTopCellToolbar | null = null; private _renderedEditors: Map = new Map(); + private _viewContext: ViewContext | undefined; private _eventDispatcher: NotebookEventDispatcher | undefined; private _notebookViewModel: NotebookViewModel | undefined; private _localStore: DisposableStore = this._register(new DisposableStore()); @@ -337,7 +339,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this.isEmbedded = creationOptions.isEmbedded || false; this.useRenderer = !isWeb && !!this.configurationService.getValue(ExperimentalUseMarkdownRenderer) && !accessibilityService.isScreenReaderOptimized(); - this._notebookOptions = new NotebookOptions(); + this._notebookOptions = new NotebookOptions(this.configurationService); this._overlayContainer = document.createElement('div'); this.scopedContextKeyService = contextKeyService.createScoped(this._overlayContainer); @@ -1161,9 +1163,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private async _attachModel(textModel: NotebookTextModel, viewState: INotebookEditorViewState | undefined) { await this._createWebview(this.getId(), textModel.uri); - this._eventDispatcher = new NotebookEventDispatcher(this._notebookOptions); - this.viewModel = this.instantiationService.createInstance(NotebookViewModel, textModel.viewType, textModel, this._eventDispatcher, this.getLayoutInfo()); - this._eventDispatcher.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]); + this._viewContext = new ViewContext(this._notebookOptions, new NotebookEventDispatcher()); + this.viewModel = this.instantiationService.createInstance(NotebookViewModel, textModel.viewType, textModel, this._viewContext, this.getLayoutInfo()); + this._viewContext.eventDispatcher.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]); this._updateForOptions(); this._updateForNotebookConfiguration(); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index 196401b6441..877255de034 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -17,7 +17,7 @@ import { CellKind, INotebookSearchOptions, ShowCellStatusBarKey, INotebookCellSt import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService'; -import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; +import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext'; export abstract class BaseCellViewModel extends Disposable { @@ -129,7 +129,7 @@ export abstract class BaseCellViewModel extends Disposable { readonly viewType: string, readonly model: NotebookCellTextModel, public id: string, - private readonly _eventDispatcher: NotebookEventDispatcher, + private readonly _viewContext: ViewContext, private readonly _configurationService: IConfigurationService, private readonly _modelService: ITextModelService, ) { @@ -152,7 +152,7 @@ export abstract class BaseCellViewModel extends Disposable { getEditorStatusbarHeight() { const showCellStatusBar = this._configurationService.getValue(ShowCellStatusBarKey); - return showCellStatusBar ? this._eventDispatcher.notebookOptions.getLayoutConfiguration().cellStatusBarHeight : 0; + return showCellStatusBar ? this._viewContext.notebookOptions.getLayoutConfiguration().cellStatusBarHeight : 0; } abstract hasDynamicHeight(): boolean; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 4a2b3fe9c12..7a81925a69f 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -11,7 +11,7 @@ import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer' import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { CellEditState, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo, CodeCellLayoutState, getEditorTopPadding, ICellOutputViewModel, ICellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; -import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; +import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { CellKind, INotebookSearchOptions, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; @@ -95,12 +95,12 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod viewType: string, model: NotebookCellTextModel, initialNotebookLayoutInfo: NotebookLayoutInfo | null, - readonly eventDispatcher: NotebookEventDispatcher, + readonly viewContext: ViewContext, @IConfigurationService configurationService: IConfigurationService, @INotebookService private readonly _notebookService: INotebookService, @ITextModelService modelService: ITextModelService, ) { - super(viewType, model, UUID.generateUuid(), eventDispatcher, configurationService, modelService); + super(viewType, model, UUID.generateUuid(), viewContext, configurationService, modelService); this._outputViewModels = this.model.outputs.map(output => new CellOutputViewModel(this, output, this._notebookService)); this._register(this.model.onDidChangeOutputs((splices) => { @@ -132,7 +132,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod fontInfo: initialNotebookLayoutInfo?.fontInfo || null, editorHeight: 0, editorWidth: initialNotebookLayoutInfo - ? this.eventDispatcher.notebookOptions.computeCodeCellEditorWidth(initialNotebookLayoutInfo.width) + ? this.viewContext.notebookOptions.computeCodeCellEditorWidth(initialNotebookLayoutInfo.width) : 0, outputContainerOffset: 0, outputTotalHeight: 0, @@ -148,7 +148,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod layoutChange(state: CodeCellLayoutChangeEvent, source?: string) { // recompute this._ensureOutputsTop(); - const notebookLayoutConfiguration = this.eventDispatcher.notebookOptions.getLayoutConfiguration(); + const notebookLayoutConfiguration = this.viewContext.notebookOptions.getLayoutConfiguration(); const outputShowMoreContainerHeight = state.outputShowMoreContainerHeight ? state.outputShowMoreContainerHeight : this._layoutInfo.outputShowMoreContainerHeight; let outputTotalHeight = Math.max(this._outputMinHeight, this.metadata?.outputCollapsed ? notebookLayoutConfiguration.collapsedIndicatorHeight : this._outputsTop!.getTotalValue()); @@ -182,9 +182,9 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod - notebookLayoutConfiguration.bottomCellToolbarGap - notebookLayoutConfiguration.bottomCellToolbarHeight / 2 - outputShowMoreContainerHeight; - const bottomToolbarOffset = this.eventDispatcher.notebookOptions.computeBottomToolbarOffset(totalHeight); + const bottomToolbarOffset = this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight); const editorWidth = state.outerWidth !== undefined - ? this.eventDispatcher.notebookOptions.computeCodeCellEditorWidth(state.outerWidth) + ? this.viewContext.notebookOptions.computeCodeCellEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth; this._layoutInfo = { @@ -215,9 +215,9 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod - notebookLayoutConfiguration.bottomCellToolbarGap - notebookLayoutConfiguration.bottomCellToolbarHeight / 2 - outputShowMoreContainerHeight; - const bottomToolbarOffset = this.eventDispatcher.notebookOptions.computeBottomToolbarOffset(totalHeight); + const bottomToolbarOffset = this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight); const editorWidth = state.outerWidth !== undefined - ? this.eventDispatcher.notebookOptions.computeCodeCellEditorWidth(state.outerWidth) + ? this.viewContext.notebookOptions.computeCodeCellEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth; this._layoutInfo = { @@ -301,12 +301,12 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod const verticalScrollbarHeight = hasScrolling ? 12 : 0; // take zoom level into account return this.lineCount * lineHeight + getEditorTopPadding() - + this.eventDispatcher.notebookOptions.getLayoutConfiguration().editorBottomPadding // EDITOR_BOTTOM_PADDING + + this.viewContext.notebookOptions.getLayoutConfiguration().editorBottomPadding // EDITOR_BOTTOM_PADDING + verticalScrollbarHeight; } private computeTotalHeight(editorHeight: number, outputsTotalHeight: number, outputShowMoreContainerHeight: number): number { - const layoutConfiguration = this.eventDispatcher.notebookOptions.getLayoutConfiguration(); + const layoutConfiguration = this.viewContext.notebookOptions.getLayoutConfiguration(); return layoutConfiguration.editorToolbarHeight //EDITOR_TOOLBAR_HEIGHT + layoutConfiguration.cellTopMargin // CELL_TOP_MARGIN + editorHeight diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher.ts index eda60b804f8..c20c60d81a0 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher.ts @@ -6,7 +6,6 @@ import { Emitter } from 'vs/base/common/event'; import { NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookLayoutChangeEvent, NotebookLayoutInfo, CellViewModelStateChangeEvent, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; export enum NotebookViewEventType { LayoutChanged = 1, @@ -50,7 +49,7 @@ export class NotebookEventDispatcher { protected readonly _onDidChangeCellState = new Emitter(); readonly onDidChangeCellState = this._onDidChangeCellState.event; - constructor(readonly notebookOptions: NotebookOptions) { + constructor() { } emit(events: NotebookViewEvent[]) { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index cb55e7f3831..f7ddea7ab60 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -12,10 +12,11 @@ import { EditorFoldingStateDelegate } from 'vs/workbench/contrib/notebook/browse import { CellEditState, CellFindMatch, ICellOutputViewModel, ICellViewModel, MarkdownCellLayoutChangeEvent, MarkdownCellLayoutInfo, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer'; import { BaseCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel'; -import { NotebookCellStateChangedEvent, NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; +import { NotebookCellStateChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { CellKind, INotebookSearchOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext'; export class MarkdownCellViewModel extends BaseCellViewModel implements ICellViewModel { readonly cellKind = CellKind.Markup; @@ -28,7 +29,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie set renderedMarkdownHeight(newHeight: number) { if (this.getEditState() === CellEditState.Preview) { - const newTotalHeight = newHeight + this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap; // BOTTOM_CELL_TOOLBAR_GAP; + const newTotalHeight = newHeight + this.viewContext.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap; // BOTTOM_CELL_TOOLBAR_GAP; this.totalHeight = newTotalHeight; } } @@ -46,7 +47,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie private _editorHeight = 0; set editorHeight(newHeight: number) { this._editorHeight = newHeight; - const layoutConfiguration = this.eventDispatcher.notebookOptions.getLayoutConfiguration(); + const layoutConfiguration = this.viewContext.notebookOptions.getLayoutConfiguration(); this.totalHeight = this._editorHeight + layoutConfiguration.markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN @@ -106,25 +107,25 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie model: NotebookCellTextModel, initialNotebookLayoutInfo: NotebookLayoutInfo | null, readonly foldingDelegate: EditorFoldingStateDelegate, - readonly eventDispatcher: NotebookEventDispatcher, + readonly viewContext: ViewContext, private readonly _mdRenderer: MarkdownRenderer, @IConfigurationService configurationService: IConfigurationService, @ITextModelService textModelService: ITextModelService, ) { - super(viewType, model, UUID.generateUuid(), eventDispatcher, configurationService, textModelService); + super(viewType, model, UUID.generateUuid(), viewContext, configurationService, textModelService); this._layoutInfo = { editorHeight: 0, fontInfo: initialNotebookLayoutInfo?.fontInfo || null, editorWidth: initialNotebookLayoutInfo?.width - ? this.eventDispatcher.notebookOptions.computeMarkdownCellEditorWidth(initialNotebookLayoutInfo.width) + ? this.viewContext.notebookOptions.computeMarkdownCellEditorWidth(initialNotebookLayoutInfo.width) : 0, - bottomToolbarOffset: this.eventDispatcher.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap, // BOTTOM_CELL_TOOLBAR_GAP, + bottomToolbarOffset: this.viewContext.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap, // BOTTOM_CELL_TOOLBAR_GAP, totalHeight: 0 }; this._register(this.onDidChangeState(e => { - eventDispatcher.emit([new NotebookCellStateChangedEvent(e, this)]); + this.viewContext.eventDispatcher.emit([new NotebookCellStateChangedEvent(e, this)]); })); this._register(model.onDidChangeMetadata(e => { @@ -154,7 +155,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie // recompute if (!this.metadata?.inputCollapsed) { const editorWidth = state.outerWidth !== undefined - ? this.eventDispatcher.notebookOptions.computeMarkdownCellEditorWidth(state.outerWidth) + ? this.viewContext.notebookOptions.computeMarkdownCellEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth; const totalHeight = state.totalHeight === undefined ? this._layoutInfo.totalHeight : state.totalHeight; @@ -162,14 +163,14 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie fontInfo: state.font || this._layoutInfo.fontInfo, editorWidth, editorHeight: this._editorHeight, - bottomToolbarOffset: this.eventDispatcher.notebookOptions.computeBottomToolbarOffset(totalHeight), + bottomToolbarOffset: this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight), totalHeight }; } else { const editorWidth = state.outerWidth !== undefined - ? this.eventDispatcher.notebookOptions.computeMarkdownCellEditorWidth(state.outerWidth) + ? this.viewContext.notebookOptions.computeMarkdownCellEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth; - const totalHeight = this.eventDispatcher.notebookOptions.computeCollapsedMarkdownCellHeight(); + const totalHeight = this.viewContext.notebookOptions.computeCollapsedMarkdownCellHeight(); state.totalHeight = totalHeight; @@ -177,7 +178,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie fontInfo: state.font || this._layoutInfo.fontInfo, editorWidth, editorHeight: this._editorHeight, - bottomToolbarOffset: this.eventDispatcher.notebookOptions.computeBottomToolbarOffset(totalHeight), + bottomToolbarOffset: this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight), totalHeight }; } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index faee24774d7..4184eb5247b 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -20,7 +20,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { CellEditState, CellFindMatch, ICellViewModel, NotebookLayoutInfo, INotebookDeltaDecoration, INotebookDeltaCellStatusBarItems, CellFocusMode, CellFindMatchWithIndex } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; -import { NotebookEventDispatcher, NotebookMetadataChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; +import { NotebookMetadataChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { CellFoldingState, EditorFoldingStateDelegate } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel'; import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; @@ -36,6 +36,7 @@ import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/ import { NotebookCellSelectionCollection } from 'vs/workbench/contrib/notebook/browser/viewModel/cellSelectionCollection'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { groupByNumber } from 'vs/base/common/collections'; +import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext'; export interface INotebookEditorViewState { editingCells: { [key: number]: boolean }; @@ -233,7 +234,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD constructor( public viewType: string, private _notebook: NotebookTextModel, - readonly eventDispatcher: NotebookEventDispatcher, + readonly viewContext: ViewContext, private _layoutInfo: NotebookLayoutInfo | null, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IBulkEditService private readonly _bulkEditService: IBulkEditService, @@ -326,7 +327,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD this._register(this._notebook.onDidChangeContent(contentChanges => { contentChanges.rawEvents.forEach(e => { if (e.kind === NotebookCellsChangeType.ChangeDocumentMetadata) { - this.eventDispatcher.emit([new NotebookMetadataChangedEvent(this._notebook.metadata)]); + this.viewContext.eventDispatcher.emit([new NotebookMetadataChangedEvent(this._notebook.metadata)]); } }); @@ -335,7 +336,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD } })); - this._register(this.eventDispatcher.onDidChangeLayout((e) => { + this._register(this.viewContext.eventDispatcher.onDidChangeLayout((e) => { this._layoutInfo = e.value; this._viewCells.forEach(cell => { @@ -1181,9 +1182,9 @@ export type CellViewModel = CodeCellViewModel | MarkdownCellViewModel; export function createCellViewModel(instantiationService: IInstantiationService, notebookViewModel: NotebookViewModel, cell: NotebookCellTextModel) { if (cell.cellKind === CellKind.Code) { - return instantiationService.createInstance(CodeCellViewModel, notebookViewModel.viewType, cell, notebookViewModel.layoutInfo, notebookViewModel.eventDispatcher); + return instantiationService.createInstance(CodeCellViewModel, notebookViewModel.viewType, cell, notebookViewModel.layoutInfo, notebookViewModel.viewContext); } else { const mdRenderer = instantiationService.createInstance(MarkdownRenderer, { baseUrl: dirname(notebookViewModel.uri) }); - return instantiationService.createInstance(MarkdownCellViewModel, notebookViewModel.viewType, cell, notebookViewModel.layoutInfo, notebookViewModel, notebookViewModel.eventDispatcher, mdRenderer); + return instantiationService.createInstance(MarkdownCellViewModel, notebookViewModel.viewType, cell, notebookViewModel.layoutInfo, notebookViewModel, notebookViewModel.viewContext, mdRenderer); } } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/viewContext.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/viewContext.ts new file mode 100644 index 00000000000..8ffe0ce0bed --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/viewContext.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; +import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; + +export class ViewContext { + constructor( + readonly notebookOptions: NotebookOptions, + readonly eventDispatcher: NotebookEventDispatcher + ) { + } +} diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index a7f3c6cd928..62bb1658bfb 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -3,6 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { IDisposable } from 'vs/base/common/lifecycle'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; + const CELL_STATUSBAR_HEIGHT = 22; const EDITOR_TOOLBAR_HEIGHT = 0; const CELL_OUTPUT_PADDING = 14; @@ -25,32 +29,36 @@ const EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR = 12; const EDITOR_BOTTOM_PADDING = 4; export interface NotebookLayoutConfiguration { - cellRightMargin: number, - cellRunGutter: number, - cellStatusBarHeight: number, - cellTopMargin: number, - cellBottomMargin: number, - cellOutputPadding: number, - codeCellLeftMargin: number, - markdownCellTopMargin: number, - markdownCellBottomMargin: number, - markdownPreviewPadding: number, - bottomCellToolbarGap: number, - bottomCellToolbarHeight: number, - editorToolbarHeight: number, - editorBottomPadding: number, - editorBottomPaddingWithoutStatusBar: number, - collapsedIndicatorHeight: number, + cellRightMargin: number; + cellRunGutter: number; + cellTopMargin: number; + cellBottomMargin: number; + cellOutputPadding: number; + codeCellLeftMargin: number; + markdownCellTopMargin: number; + markdownCellBottomMargin: number; + markdownPreviewPadding: number; + bottomCellToolbarGap: number; + bottomCellToolbarHeight: number; + editorToolbarHeight: number; + editorBottomPadding: number; + editorBottomPaddingWithoutStatusBar: number; + collapsedIndicatorHeight: number; + showCellStatusBar: boolean; + cellStatusBarHeight: number; } export class NotebookOptions { private _layoutConfiguration: NotebookLayoutConfiguration; + private _disposables: IDisposable[]; - constructor() { + constructor(readonly configurationService: IConfigurationService) { + const showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); + + this._disposables = []; this._layoutConfiguration = { cellRightMargin: CELL_RIGHT_MARGIN, cellRunGutter: CELL_RUN_GUTTER, - cellStatusBarHeight: CELL_STATUSBAR_HEIGHT, cellTopMargin: CELL_TOP_MARGIN, cellBottomMargin: CELL_BOTTOM_MARGIN, codeCellLeftMargin: CODE_CELL_LEFT_MARGIN, @@ -63,8 +71,19 @@ export class NotebookOptions { editorToolbarHeight: EDITOR_TOOLBAR_HEIGHT, cellOutputPadding: CELL_OUTPUT_PADDING, collapsedIndicatorHeight: COLLAPSED_INDICATOR_HEIGHT, - markdownPreviewPadding: MARKDOWN_PREVIEW_PADDING + markdownPreviewPadding: MARKDOWN_PREVIEW_PADDING, + cellStatusBarHeight: CELL_STATUSBAR_HEIGHT, + showCellStatusBar }; + + this._disposables.push(this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(ShowCellStatusBarKey)) { + const configuration = Object.assign({}, this._layoutConfiguration); + configuration.showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); + this._layoutConfiguration = configuration; + // trigger event + } + })); } getLayoutConfiguration(): NotebookLayoutConfiguration { diff --git a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts index a0c9fd65a35..78f6e82be8a 100644 --- a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts +++ b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts @@ -18,6 +18,7 @@ import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { reduceCellRanges } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; +import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { CellKind, diff, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; @@ -38,8 +39,8 @@ suite('NotebookViewModel', () => { test('ctor', function () { const notebook = new NotebookTextModel('notebook', URI.parse('test'), [], notebookDocumentMetadataDefaults, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false }, undoRedoService, modelService, modeService); const model = new NotebookEditorTestModel(notebook); - const eventDispatcher = new NotebookEventDispatcher(new NotebookOptions()); - const viewModel = new NotebookViewModel('notebook', model.notebook, eventDispatcher, null, instantiationService, bulkEditService, undoRedoService, textModelService); + const viewContext = new ViewContext(new NotebookOptions(instantiationService.get(IConfigurationService)), new NotebookEventDispatcher()); + const viewModel = new NotebookViewModel('notebook', model.notebook, viewContext, null, instantiationService, bulkEditService, undoRedoService, textModelService); assert.strictEqual(viewModel.viewType, 'notebook'); }); diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index c19601ab84f..7ec10b0a28e 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -43,6 +43,7 @@ import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServic import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust'; import { TestWorkspaceTrustRequestService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService'; import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; +import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext'; export class TestCell extends NotebookCellTextModel { constructor( @@ -172,8 +173,8 @@ function _createTestNotebookEditor(instantiationService: TestInstantiationServic }), notebookDocumentMetadataDefaults, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false }); const model = new NotebookEditorTestModel(notebook); - const eventDispatcher = new NotebookEventDispatcher(new NotebookOptions()); - const viewModel: NotebookViewModel = instantiationService.createInstance(NotebookViewModel, viewType, model.notebook, eventDispatcher, null); + const viewContext = new ViewContext(new NotebookOptions(instantiationService.get(IConfigurationService)), new NotebookEventDispatcher()); + const viewModel: NotebookViewModel = instantiationService.createInstance(NotebookViewModel, viewType, model.notebook, viewContext, null); const cellList = createNotebookCellList(instantiationService); cellList.attachViewModel(viewModel); From 46a57578347619f50af39d158fcb0783d92c98b3 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 16:42:33 -0700 Subject: [PATCH 08/76] add cell status bar configuration handling in notebook options. --- .../notebook/browser/contrib/fold/folding.ts | 2 +- .../notebook/browser/notebookEditorWidget.ts | 17 +++++++++++------ .../browser/view/renderers/cellEditorOptions.ts | 12 +++++++++--- .../browser/viewModel/baseCellViewModel.ts | 11 ++++++----- .../contrib/notebook/common/notebookOptions.ts | 17 +++++++++++++++++ 5 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/fold/folding.ts b/src/vs/workbench/contrib/notebook/browser/contrib/fold/folding.ts index f3fda701c19..73e57fe8921 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/fold/folding.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/fold/folding.ts @@ -38,7 +38,7 @@ export class FoldingController extends Disposable implements INotebookEditorCont return; } - this._localStore.add(this._notebookEditor.viewModel.eventDispatcher.onDidChangeCellState(e => { + this._localStore.add(this._notebookEditor.viewModel.viewContext.eventDispatcher.onDidChangeCellState(e => { if (e.source.editStateChanged && e.cell.cellKind === CellKind.Markup) { this._foldingModel?.recompute(); // this._updateEditorFoldingRanges(); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 04bede842fa..b1d1812e2bf 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -58,7 +58,7 @@ import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbenc import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; 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, CellToolbarVisibility, ExperimentalUseMarkdownRenderer, SelectionStateType, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, CellToolbarLocKey, CellToolbarVisibility, ExperimentalUseMarkdownRenderer, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator'; import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; @@ -217,7 +217,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor private _listTopCellToolbar: ListTopCellToolbar | null = null; private _renderedEditors: Map = new Map(); private _viewContext: ViewContext | undefined; - private _eventDispatcher: NotebookEventDispatcher | undefined; private _notebookViewModel: NotebookViewModel | undefined; private _localStore: DisposableStore = this._register(new DisposableStore()); private _localCellStateListeners: DisposableStore[] = []; @@ -367,7 +366,13 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } } - if (e.affectsConfiguration(CellToolbarLocKey) || e.affectsConfiguration(ShowCellStatusBarKey) || e.affectsConfiguration(CellToolbarVisibility)) { + if (e.affectsConfiguration(CellToolbarLocKey) || e.affectsConfiguration(CellToolbarVisibility)) { + this._updateForNotebookConfiguration(); + } + })); + + this._register(this._notebookOptions.onDidChangeOptions(e => { + if (e.cellStatusBarVisibility) { this._updateForNotebookConfiguration(); } })); @@ -531,7 +536,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } } - const showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); + const showCellStatusBar = this._notebookOptions.getLayoutConfiguration().showCellStatusBar; this._overlayContainer.classList.toggle('cell-statusbar-hidden', !showCellStatusBar); const cellToolbarInteraction = this.configurationService.getValue(CellToolbarVisibility); @@ -1519,7 +1524,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._webviewTransparentCover.style.width = `${dimension.width}px`; } - this._eventDispatcher?.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]); + this._viewContext?.eventDispatcher.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]); } //#endregion @@ -2532,7 +2537,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._webviewTransparentCover = null; this._dndController = null; this._listTopCellToolbar = null; - this._eventDispatcher = undefined; + this._viewContext = undefined; this._notebookViewModel = undefined; this._cellContextKeyManager = null; this._renderedEditors.clear(); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts index 1a078ecf9d8..2f41d801271 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts @@ -11,7 +11,6 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'v import { IEditorOptions, LineNumbersType } from 'vs/editor/common/config/editorOptions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { EditorTopPaddingChangeEvent, getEditorTopPadding, getNotebookEditorFromEditorPane, ICellViewModel, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { localize } from 'vs/nls'; import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -51,7 +50,14 @@ export class CellEditorOptions extends Disposable { constructor(readonly notebookOptions: NotebookOptions, readonly configurationService: IConfigurationService, language: string) { super(); this._register(configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration('editor') || e.affectsConfiguration('notebook') || e.affectsConfiguration(ShowCellStatusBarKey)) { + if (e.affectsConfiguration('editor') || e.affectsConfiguration('notebook')) { + this._value = computeEditorOptions(); + this._onDidChange.fire(this.value); + } + })); + + this._register(notebookOptions.onDidChangeOptions(e => { + if (e.cellStatusBarVisibility) { this._value = computeEditorOptions(); this._onDidChange.fire(this.value); } @@ -63,7 +69,7 @@ export class CellEditorOptions extends Disposable { })); const computeEditorOptions = () => { - const showCellStatusBar = configurationService.getValue(ShowCellStatusBarKey); + const showCellStatusBar = this.notebookOptions.getLayoutConfiguration().showCellStatusBar; const editorPadding = { top: getEditorTopPadding(), bottom: showCellStatusBar diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index 877255de034..a1991a51fa1 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -13,7 +13,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import * as model from 'vs/editor/common/model'; import { SearchParams } from 'vs/editor/common/model/textModelSearch'; import { CellEditState, CellFocusMode, CursorAtBoundary, CellViewModelStateChangeEvent, IEditableCellViewModel, INotebookCellDecorationOptions, getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { CellKind, INotebookSearchOptions, ShowCellStatusBarKey, INotebookCellStatusBarItem } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, INotebookSearchOptions, INotebookCellStatusBarItem } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService'; @@ -139,11 +139,13 @@ export abstract class BaseCellViewModel extends Disposable { this._onDidChangeState.fire({ metadataChanged: true, runStateChanged: e.runStateChanged }); })); - this._register(this._configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration(ShowCellStatusBarKey)) { + this._register(this._viewContext.notebookOptions.onDidChangeOptions(e => { + if (e.cellStatusBarVisibility) { this.layoutChange({}); } + })); + this._register(this._configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('notebook.lineNumbers')) { this.lineNumbers = 'inherit'; } @@ -151,8 +153,7 @@ export abstract class BaseCellViewModel extends Disposable { } getEditorStatusbarHeight() { - const showCellStatusBar = this._configurationService.getValue(ShowCellStatusBarKey); - return showCellStatusBar ? this._viewContext.notebookOptions.getLayoutConfiguration().cellStatusBarHeight : 0; + return this._viewContext.notebookOptions.computeStatusBarHeight(); } abstract hasDynamicHeight(): boolean; diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 62bb1658bfb..abf2b786d37 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; @@ -48,8 +49,13 @@ export interface NotebookLayoutConfiguration { cellStatusBarHeight: number; } +interface NotebookOptionsChangeEvent { + cellStatusBarVisibility?: boolean; +} export class NotebookOptions { private _layoutConfiguration: NotebookLayoutConfiguration; + protected readonly _onDidChangeOptions = new Emitter(); + readonly onDidChangeOptions = this._onDidChangeOptions.event; private _disposables: IDisposable[]; constructor(readonly configurationService: IConfigurationService) { @@ -82,6 +88,9 @@ export class NotebookOptions { configuration.showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); this._layoutConfiguration = configuration; // trigger event + this._onDidChangeOptions.fire({ + cellStatusBarVisibility: true + }); } })); } @@ -116,4 +125,12 @@ export class NotebookOptions { - this._layoutConfiguration.codeCellLeftMargin // CODE_CELL_LEFT_MARGIN - this._layoutConfiguration.cellRightMargin; // CELL_RIGHT_MARGIN; } + + computeStatusBarHeight(): number { + if (this._layoutConfiguration.showCellStatusBar) { + return this._layoutConfiguration.cellStatusBarHeight; + } else { + return 0; + } + } } From db0cea611b8cf22162abb27b7b8104894d51e2a7 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 16:53:23 -0700 Subject: [PATCH 09/76] fix cell toolbar position for hidden. --- .../workbench/contrib/notebook/browser/notebookEditorWidget.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index b1d1812e2bf..96cb3efe81f 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -523,8 +523,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor break; case 'right': cellToolbarLocationForCurrentView = 'right'; + break; case 'hidden': cellToolbarLocationForCurrentView = 'hidden'; + break; default: cellToolbarLocationForCurrentView = 'right'; break; From 662cdc5e847d17cff17702644530d63c99874f9e Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 17:08:32 -0700 Subject: [PATCH 10/76] move cell toolbar location setting into notebook options. --- .../notebook/browser/notebookEditorWidget.ts | 43 ++-------- .../notebook/common/notebookOptions.ts | 83 ++++++++++++++++--- 2 files changed, 78 insertions(+), 48 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 96cb3efe81f..b3908eeace5 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -58,7 +58,7 @@ import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbenc import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; 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, CellToolbarVisibility, ExperimentalUseMarkdownRenderer, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, ExperimentalUseMarkdownRenderer, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator'; import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; @@ -365,14 +365,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this.layout(this._dimension); } } - - if (e.affectsConfiguration(CellToolbarLocKey) || e.affectsConfiguration(CellToolbarVisibility)) { - this._updateForNotebookConfiguration(); - } })); this._register(this._notebookOptions.onDidChangeOptions(e => { - if (e.cellStatusBarVisibility) { + if (e.cellStatusBarVisibility || e.cellToolbarLocation || e.cellToolbarInteraction) { this._updateForNotebookConfiguration(); } })); @@ -503,45 +499,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return; } - const cellToolbarLocation = this.configurationService.getValue(CellToolbarLocKey); this._overlayContainer.classList.remove('cell-title-toolbar-left'); this._overlayContainer.classList.remove('cell-title-toolbar-right'); this._overlayContainer.classList.remove('cell-title-toolbar-hidden'); - - if (typeof cellToolbarLocation === 'string') { - if (cellToolbarLocation === 'left' || cellToolbarLocation === 'right' || cellToolbarLocation === 'hidden') { - this._overlayContainer.classList.add(`cell-title-toolbar-${cellToolbarLocation}`); - } - } else { - if (this.viewModel) { - const notebookSpecificSetting = cellToolbarLocation[this.viewModel.viewType] ?? cellToolbarLocation['default']; - let cellToolbarLocationForCurrentView = 'right'; - - switch (notebookSpecificSetting) { - case 'left': - cellToolbarLocationForCurrentView = 'left'; - break; - case 'right': - cellToolbarLocationForCurrentView = 'right'; - break; - case 'hidden': - cellToolbarLocationForCurrentView = 'hidden'; - break; - default: - cellToolbarLocationForCurrentView = 'right'; - break; - } - - this._overlayContainer.classList.add(`cell-title-toolbar-${cellToolbarLocationForCurrentView}`); - } else { - this._overlayContainer.classList.add(`cell-title-toolbar-right`); - } - } + const cellToolbarLocation = this._notebookOptions.computeCellToolbarLocation(this.viewModel?.viewType); + this._overlayContainer.classList.add(`cell-title-toolbar-${cellToolbarLocation}`); const showCellStatusBar = this._notebookOptions.getLayoutConfiguration().showCellStatusBar; this._overlayContainer.classList.toggle('cell-statusbar-hidden', !showCellStatusBar); - const cellToolbarInteraction = this.configurationService.getValue(CellToolbarVisibility); + const cellToolbarInteraction = this._notebookOptions.getLayoutConfiguration().cellToolbarInteraction; let cellToolbarInteractionState = 'hover'; this._overlayContainer.classList.remove('cell-toolbar-hover'); this._overlayContainer.classList.remove('cell-toolbar-click'); diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index abf2b786d37..e9a37b1176e 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -6,7 +6,7 @@ import { Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellToolbarLocKey, CellToolbarVisibility, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; const CELL_STATUSBAR_HEIGHT = 22; const EDITOR_TOOLBAR_HEIGHT = 0; @@ -47,10 +47,14 @@ export interface NotebookLayoutConfiguration { collapsedIndicatorHeight: number; showCellStatusBar: boolean; cellStatusBarHeight: number; + cellToolbarLocation: string | { [key: string]: string }; + cellToolbarInteraction: string; } interface NotebookOptionsChangeEvent { cellStatusBarVisibility?: boolean; + cellToolbarLocation?: boolean; + cellToolbarInteraction?: boolean; } export class NotebookOptions { private _layoutConfiguration: NotebookLayoutConfiguration; @@ -60,6 +64,8 @@ export class NotebookOptions { constructor(readonly configurationService: IConfigurationService) { const showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); + const cellToolbarLocation = this.configurationService.getValue(CellToolbarLocKey); + const cellToolbarInteraction = this.configurationService.getValue(CellToolbarVisibility); this._disposables = []; this._layoutConfiguration = { @@ -79,19 +85,42 @@ export class NotebookOptions { collapsedIndicatorHeight: COLLAPSED_INDICATOR_HEIGHT, markdownPreviewPadding: MARKDOWN_PREVIEW_PADDING, cellStatusBarHeight: CELL_STATUSBAR_HEIGHT, - showCellStatusBar + showCellStatusBar, + cellToolbarLocation, + cellToolbarInteraction }; this._disposables.push(this.configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration(ShowCellStatusBarKey)) { - const configuration = Object.assign({}, this._layoutConfiguration); - configuration.showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); - this._layoutConfiguration = configuration; - // trigger event - this._onDidChangeOptions.fire({ - cellStatusBarVisibility: true - }); + let cellStatusBarVisibility = e.affectsConfiguration(ShowCellStatusBarKey); + let cellToolbarLocation = e.affectsConfiguration(CellToolbarLocKey); + let cellToolbarInteraction = e.affectsConfiguration(CellToolbarVisibility); + + if (!cellStatusBarVisibility && !cellToolbarLocation && !cellToolbarInteraction) { + return; } + + const configuration = Object.assign({}, this._layoutConfiguration); + + if (cellStatusBarVisibility) { + configuration.showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); + } + + if (cellToolbarLocation) { + configuration.cellToolbarLocation = this.configurationService.getValue(CellToolbarLocKey); + } + + if (cellToolbarInteraction) { + configuration.cellToolbarInteraction = this.configurationService.getValue(CellToolbarVisibility); + } + + this._layoutConfiguration = configuration; + + // trigger event + this._onDidChangeOptions.fire({ + cellStatusBarVisibility: cellStatusBarVisibility, + cellToolbarLocation: cellToolbarLocation, + cellToolbarInteraction: cellToolbarInteraction + }); })); } @@ -133,4 +162,38 @@ export class NotebookOptions { return 0; } } + + computeCellToolbarLocation(viewType?: string): 'right' | 'left' | 'hidden' { + const cellToolbarLocation = this._layoutConfiguration.cellToolbarLocation; + + if (typeof cellToolbarLocation === 'string') { + if (cellToolbarLocation === 'left' || cellToolbarLocation === 'right' || cellToolbarLocation === 'hidden') { + return cellToolbarLocation; + } + } else { + if (viewType) { + const notebookSpecificSetting = cellToolbarLocation[viewType] ?? cellToolbarLocation['default']; + let cellToolbarLocationForCurrentView: 'right' | 'left' | 'hidden' = 'right'; + + switch (notebookSpecificSetting) { + case 'left': + cellToolbarLocationForCurrentView = 'left'; + break; + case 'right': + cellToolbarLocationForCurrentView = 'right'; + break; + case 'hidden': + cellToolbarLocationForCurrentView = 'hidden'; + break; + default: + cellToolbarLocationForCurrentView = 'right'; + break; + } + + return cellToolbarLocationForCurrentView; + } + } + + return 'right'; + } } From 3cdf41aa1c6455aa483c1431eb5a60d778d1901b Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 17:58:53 -0700 Subject: [PATCH 11/76] compute editor padding. --- .../notebook/browser/diff/diffComponents.ts | 11 ++++--- .../notebook/browser/notebookBrowser.ts | 16 +-------- .../notebook/browser/notebookServiceImpl.ts | 3 +- .../view/renderers/cellEditorOptions.ts | 18 ++-------- .../browser/view/renderers/codeCell.ts | 6 ++-- .../browser/view/renderers/markdownCell.ts | 5 +-- .../browser/viewModel/baseCellViewModel.ts | 8 +++-- .../browser/viewModel/codeCellViewModel.ts | 7 ++-- .../notebook/common/notebookOptions.ts | 33 +++++++++++++++++++ 9 files changed, 62 insertions(+), 45 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 5cb5beb2cb4..18f142fe53f 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -25,7 +25,6 @@ import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/men import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { Delayer } from 'vs/base/common/async'; import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellActionView'; -import { getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { collapsedIcon, expandedIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/diff/diffElementOutputs'; import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions'; @@ -979,7 +978,8 @@ export class DeletedElement extends SingleSideDiffElement { const originalCell = this.cell.original!; const lineCount = originalCell.textModel.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; - const editorHeight = lineCount * lineHeight + getEditorTopPadding() + this.notebookEditor.notebookOptions.getLayoutConfiguration().editorBottomPadding; + const editorPadding = this.notebookEditor.notebookOptions.computeEditorPadding(); + const editorHeight = lineCount * lineHeight + editorPadding.top + editorPadding.bottom; this._editor = this.templateData.sourceEditor; this._editor.layout({ @@ -1130,7 +1130,8 @@ export class InsertElement extends SingleSideDiffElement { const modifiedCell = this.cell.modified!; const lineCount = modifiedCell.textModel.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; - const editorHeight = lineCount * lineHeight + getEditorTopPadding() + this.notebookEditor.notebookOptions.getLayoutConfiguration().editorBottomPadding; + const editorPadding = this.notebookEditor.notebookOptions.computeEditorPadding(); + const editorHeight = lineCount * lineHeight + editorPadding.top + editorPadding.bottom; this._editor = this.templateData.sourceEditor; this._editor.layout( @@ -1468,7 +1469,9 @@ export class ModifiedElement extends AbstractElementRenderer { const modifiedCell = this.cell.modified!; const lineCount = modifiedCell.textModel.textBuffer.getLineCount(); const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17; - const editorHeight = this.cell.layoutInfo.editorHeight !== 0 ? this.cell.layoutInfo.editorHeight : lineCount * lineHeight + getEditorTopPadding() + this.notebookEditor.notebookOptions.getLayoutConfiguration().editorBottomPadding; + const editorPadding = this.notebookEditor.notebookOptions.computeEditorPadding(); + + const editorHeight = this.cell.layoutInfo.editorHeight !== 0 ? this.cell.layoutInfo.editorHeight : lineCount * lineHeight + editorPadding.top + editorPadding.bottom; this._editorContainer = this.templateData.editorContainer; this._editor = this.templateData.sourceEditor; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 57fb30b69d1..fd69c02aa50 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -8,7 +8,7 @@ import { IListContextMenuEvent, IListEvent, IListMouseEvent } from 'vs/base/brow import { IListOptions, IListStyles } from 'vs/base/browser/ui/list/listWidget'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; -import { Emitter, Event } from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { ScrollEvent } from 'vs/base/common/scrollable'; import { URI } from 'vs/base/common/uri'; @@ -910,20 +910,6 @@ export function getNotebookEditorFromEditorPane(editorPane?: IEditorPane): INote return editorPane?.getId() === NOTEBOOK_EDITOR_ID ? editorPane.getControl() as INotebookEditor | undefined : undefined; } -let EDITOR_TOP_PADDING = 12; -const editorTopPaddingChangeEmitter = new Emitter(); - -export const EditorTopPaddingChangeEvent = editorTopPaddingChangeEmitter.event; - -export function updateEditorTopPadding(top: number) { - EDITOR_TOP_PADDING = top; - editorTopPaddingChangeEmitter.fire(); -} - -export function getEditorTopPadding() { - return EDITOR_TOP_PADDING; -} - /** * ranges: model selections * this will convert model selections to view indexes first, and then include the hidden ranges in the list view diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index c8cc2383e76..a43565b2204 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -28,13 +28,14 @@ import { IEditorInput } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { Memento } from 'vs/workbench/common/memento'; import { INotebookEditorContribution, notebookMarkupRendererExtensionPoint, notebooksExtensionPoint, notebookRendererExtensionPoint, notebooksExtensionPoint2 } from 'vs/workbench/contrib/notebook/browser/extensionPoint'; -import { NotebookEditorOptions, updateEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { NotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookDiffEditorInput'; 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, CellUri, DisplayOrderKey, INotebookExclusiveDocumentFilter, INotebookMarkupRendererInfo, INotebookContributionData, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, IOutputDto, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, NotebookDataDto, NotebookEditorPriority, NotebookRendererMatch, NotebookTextDiffEditorPreview, RENDERER_NOT_AVAILABLE, sortMimeTypes, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; import { NotebookMarkupRendererInfo as NotebookMarkupRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookMarkdownRenderer'; +import { updateEditorTopPadding } from 'vs/workbench/contrib/notebook/common/notebookOptions'; import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer'; import { NotebookEditorDescriptor, NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider'; import { ComplexNotebookProviderInfo, INotebookContentProvider, INotebookSerializer, INotebookService, SimpleNotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookService'; diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts index 2f41d801271..6cfebf38da7 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts @@ -10,7 +10,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IEditorOptions, LineNumbersType } from 'vs/editor/common/config/editorOptions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { EditorTopPaddingChangeEvent, getEditorTopPadding, getNotebookEditorFromEditorPane, ICellViewModel, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { getNotebookEditorFromEditorPane, ICellViewModel, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { localize } from 'vs/nls'; import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -57,26 +57,14 @@ export class CellEditorOptions extends Disposable { })); this._register(notebookOptions.onDidChangeOptions(e => { - if (e.cellStatusBarVisibility) { + if (e.cellStatusBarVisibility || e.editorTopPadding) { this._value = computeEditorOptions(); this._onDidChange.fire(this.value); } })); - this._register(EditorTopPaddingChangeEvent(() => { - this._value = computeEditorOptions(); - this._onDidChange.fire(this.value); - })); - const computeEditorOptions = () => { - const showCellStatusBar = this.notebookOptions.getLayoutConfiguration().showCellStatusBar; - const editorPadding = { - top: getEditorTopPadding(), - bottom: showCellStatusBar - ? this.notebookOptions.getLayoutConfiguration().editorBottomPadding// EDITOR_BOTTOM_PADDING - : this.notebookOptions.getLayoutConfiguration().editorBottomPaddingWithoutStatusBar // EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR - }; - + const editorPadding = this.notebookOptions.computeEditorPadding(); const renderLiNumbers = configurationService.getValue<'on' | 'off'>('notebook.lineNumbers') === 'on'; const lineNumbers: LineNumbersType = renderLiNumbers ? 'on' : 'off'; const editorOptions = deepClone(configurationService.getValue('editor', { overrideIdentifier: language })); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index 9a49ddec4f7..9e7058f4dba 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -10,7 +10,7 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IDimension } from 'vs/editor/common/editorCommon'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { CellFocusMode, CodeCellRenderTemplate, getEditorTopPadding, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellFocusMode, CodeCellRenderTemplate, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellOutputContainer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellOutput'; import { ClickTargetType } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; @@ -39,8 +39,10 @@ export class CodeCell extends Disposable { const width = this.viewCell.layoutInfo.editorWidth; const lineNum = this.viewCell.lineCount; const lineHeight = this.viewCell.layoutInfo.fontInfo?.lineHeight || 17; + const editorPadding = this.notebookEditor.notebookOptions.computeEditorPadding(); + const editorHeight = this.viewCell.layoutInfo.editorHeight === 0 - ? lineNum * lineHeight + getEditorTopPadding() + this.notebookEditor.notebookOptions.getLayoutConfiguration().editorBottomPadding // EDITOR_BOTTOM_PADDING + ? lineNum * lineHeight + editorPadding.top + editorPadding.bottom : this.viewCell.layoutInfo.editorHeight; this.layoutEditor( diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index a12a464e70d..8da7491ee30 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -10,7 +10,7 @@ import { Disposable, DisposableStore, IDisposable, MutableDisposable, toDisposab import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { CellEditState, CellFocusMode, MarkdownCellRenderTemplate, ICellViewModel, getEditorTopPadding, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, CellFocusMode, MarkdownCellRenderTemplate, ICellViewModel, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellFoldingState } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel'; import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -294,7 +294,8 @@ export class StatefulMarkdownCell extends Disposable { const width = this.viewCell.layoutInfo.editorWidth; const lineNum = this.viewCell.lineCount; const lineHeight = this.viewCell.layoutInfo.fontInfo?.lineHeight || 17; - editorHeight = Math.max(lineNum, 1) * lineHeight + getEditorTopPadding() + this.notebookEditor.notebookOptions.getLayoutConfiguration().editorBottomPadding; + const editorPadding = this.notebookEditor.notebookOptions.computeEditorPadding(); + editorHeight = Math.max(lineNum, 1) * lineHeight + editorPadding.top + editorPadding.bottom; this.templateData.editorContainer.innerText = ''; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index a1991a51fa1..8ed3cb6b951 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -12,7 +12,7 @@ import { IPosition } from 'vs/editor/common/core/position'; import * as editorCommon from 'vs/editor/common/editorCommon'; import * as model from 'vs/editor/common/model'; import { SearchParams } from 'vs/editor/common/model/textModelSearch'; -import { CellEditState, CellFocusMode, CursorAtBoundary, CellViewModelStateChangeEvent, IEditableCellViewModel, INotebookCellDecorationOptions, getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, CellFocusMode, CursorAtBoundary, CellViewModelStateChangeEvent, IEditableCellViewModel, INotebookCellDecorationOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellKind, INotebookSearchOptions, INotebookCellStatusBarItem } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -396,7 +396,8 @@ export abstract class BaseCellViewModel extends Disposable { return 0; } - return this._textEditor.getTopForLineNumber(line) + getEditorTopPadding(); + const editorPadding = this._viewContext.notebookOptions.computeEditorPadding(); + return this._textEditor.getTopForLineNumber(line) + editorPadding.top; } getPositionScrollTopOffset(line: number, column: number): number { @@ -404,7 +405,8 @@ export abstract class BaseCellViewModel extends Disposable { return 0; } - return this._textEditor.getTopForPosition(line, column) + getEditorTopPadding(); + const editorPadding = this._viewContext.notebookOptions.computeEditorPadding(); + return this._textEditor.getTopForPosition(line, column) + editorPadding.top; } cursorAtBoundary(): CursorAtBoundary { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 7a81925a69f..70e00498851 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -9,7 +9,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { CellEditState, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo, CodeCellLayoutState, getEditorTopPadding, ICellOutputViewModel, ICellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo, CodeCellLayoutState, ICellOutputViewModel, ICellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel'; import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; @@ -299,9 +299,10 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod } const verticalScrollbarHeight = hasScrolling ? 12 : 0; // take zoom level into account + const editorPadding = this.viewContext.notebookOptions.computeEditorPadding(); return this.lineCount * lineHeight - + getEditorTopPadding() - + this.viewContext.notebookOptions.getLayoutConfiguration().editorBottomPadding // EDITOR_BOTTOM_PADDING + + editorPadding.top + + editorPadding.bottom // EDITOR_BOTTOM_PADDING + verticalScrollbarHeight; } diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index e9a37b1176e..9a2e8414c95 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -29,6 +29,20 @@ const COLLAPSED_INDICATOR_HEIGHT = 24; const EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR = 12; const EDITOR_BOTTOM_PADDING = 4; +let EDITOR_TOP_PADDING = 12; +const editorTopPaddingChangeEmitter = new Emitter(); + +export const EditorTopPaddingChangeEvent = editorTopPaddingChangeEmitter.event; + +export function updateEditorTopPadding(top: number) { + EDITOR_TOP_PADDING = top; + editorTopPaddingChangeEmitter.fire(); +} + +export function getEditorTopPadding() { + return EDITOR_TOP_PADDING; +} + export interface NotebookLayoutConfiguration { cellRightMargin: number; cellRunGutter: number; @@ -42,6 +56,7 @@ export interface NotebookLayoutConfiguration { bottomCellToolbarGap: number; bottomCellToolbarHeight: number; editorToolbarHeight: number; + editorTopPadding: number; editorBottomPadding: number; editorBottomPaddingWithoutStatusBar: number; collapsedIndicatorHeight: number; @@ -55,6 +70,7 @@ interface NotebookOptionsChangeEvent { cellStatusBarVisibility?: boolean; cellToolbarLocation?: boolean; cellToolbarInteraction?: boolean; + editorTopPadding?: boolean; } export class NotebookOptions { private _layoutConfiguration: NotebookLayoutConfiguration; @@ -78,6 +94,7 @@ export class NotebookOptions { markdownCellBottomMargin: MARKDOWN_CELL_BOTTOM_MARGIN, bottomCellToolbarGap: BOTTOM_CELL_TOOLBAR_GAP, bottomCellToolbarHeight: BOTTOM_CELL_TOOLBAR_HEIGHT, + editorTopPadding: EDITOR_TOP_PADDING, editorBottomPadding: EDITOR_BOTTOM_PADDING, editorBottomPaddingWithoutStatusBar: EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR, editorToolbarHeight: EDITOR_TOOLBAR_HEIGHT, @@ -122,6 +139,13 @@ export class NotebookOptions { cellToolbarInteraction: cellToolbarInteraction }); })); + + this._disposables.push(EditorTopPaddingChangeEvent(() => { + const configuration = Object.assign({}, this._layoutConfiguration); + configuration.editorTopPadding = getEditorTopPadding(); + this._layoutConfiguration = configuration; + this._onDidChangeOptions.fire({ editorTopPadding: true }); + })); } getLayoutConfiguration(): NotebookLayoutConfiguration { @@ -196,4 +220,13 @@ export class NotebookOptions { return 'right'; } + + computeEditorPadding() { + return { + top: getEditorTopPadding(), + bottom: this._layoutConfiguration.showCellStatusBar + ? this._layoutConfiguration.editorBottomPadding// EDITOR_BOTTOM_PADDING + : this._layoutConfiguration.editorBottomPaddingWithoutStatusBar // EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR + }; + } } From ddf02aee48769b8ca546f55901d6af1590fee75c Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 18:07:08 -0700 Subject: [PATCH 12/76] compute webview options. --- .../browser/diff/notebookTextDiffEditor.ts | 18 ++------------- .../notebook/browser/notebookEditorWidget.ts | 10 +-------- .../viewModel/markdownCellViewModel.ts | 2 +- .../notebook/common/notebookOptions.ts | 22 +++++++++++++++++++ 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index d6c16589001..12257d62add 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -377,14 +377,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._modifiedWebview.dispose(); } - this._modifiedWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, { - outputNodePadding: this._notebookOptions.getLayoutConfiguration().cellOutputPadding, // CELL_OUTPUT_PADDING, - outputNodeLeftPadding: 32, - previewNodePadding: this._notebookOptions.getLayoutConfiguration().markdownPreviewPadding, // MARKDOWN_PREVIEW_PADDING, - leftMargin: 0, - rightMargin: 0, - runGutter: 0 - }) as BackLayerWebView; + this._modifiedWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, this._notebookOptions.computeDiffWebviewOptions()) as BackLayerWebView; // attach the webview container to the DOM tree first this._list.rowsContainer.insertAdjacentElement('afterbegin', this._modifiedWebview.element); await this._modifiedWebview.createWebview(); @@ -397,14 +390,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._originalWebview.dispose(); } - this._originalWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, { - outputNodePadding: this._notebookOptions.getLayoutConfiguration().cellOutputPadding, // CELL_OUTPUT_PADDING, - outputNodeLeftPadding: 32, - previewNodePadding: this._notebookOptions.getLayoutConfiguration().markdownPreviewPadding, // MARKDOWN_PREVIEW_PADDING, - leftMargin: 0, - rightMargin: 0, - runGutter: 0 - }) as BackLayerWebView; + this._originalWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, this._notebookOptions.computeDiffWebviewOptions()) as BackLayerWebView; // attach the webview container to the DOM tree first this._list.rowsContainer.insertAdjacentElement('afterbegin', this._originalWebview.element); await this._originalWebview.createWebview(); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index b3908eeace5..b24ce3d3957 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1119,15 +1119,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } private async _createWebview(id: string, resource: URI): Promise { - const layoutConfiguration = this._notebookOptions.getLayoutConfiguration(); - this._webview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, { - outputNodePadding: layoutConfiguration.cellOutputPadding, // CELL_OUTPUT_PADDING, - outputNodeLeftPadding: layoutConfiguration.cellOutputPadding, // CELL_OUTPUT_PADDING, - previewNodePadding: layoutConfiguration.markdownPreviewPadding, // MARKDOWN_PREVIEW_PADDING, - leftMargin: layoutConfiguration.codeCellLeftMargin, // CODE_CELL_LEFT_MARGIN, - rightMargin: layoutConfiguration.cellRightMargin, // CELL_RIGHT_MARGIN, - runGutter: layoutConfiguration.cellRunGutter, // CELL_RUN_GUTTER, - }); + this._webview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, this._notebookOptions.computeWebviewOptions()); this._webview.element.style.width = '100%'; // attach the webview container to the DOM tree first diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index f7ddea7ab60..fc457a84707 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -53,7 +53,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie + layoutConfiguration.markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN + layoutConfiguration.markdownCellBottomMargin // MARKDOWN_CELL_BOTTOM_MARGIN + layoutConfiguration.bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP - + this.getEditorStatusbarHeight(); + + this.viewContext.notebookOptions.computeStatusBarHeight(); } get editorHeight() { diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 9a2e8414c95..d0fe5ca3b68 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -229,4 +229,26 @@ export class NotebookOptions { : this._layoutConfiguration.editorBottomPaddingWithoutStatusBar // EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR }; } + + computeWebviewOptions() { + return { + outputNodePadding: this._layoutConfiguration.cellOutputPadding, // CELL_OUTPUT_PADDING, + outputNodeLeftPadding: this._layoutConfiguration.cellOutputPadding, // CELL_OUTPUT_PADDING, + previewNodePadding: this._layoutConfiguration.markdownPreviewPadding, // MARKDOWN_PREVIEW_PADDING, + leftMargin: this._layoutConfiguration.codeCellLeftMargin, // CODE_CELL_LEFT_MARGIN, + rightMargin: this._layoutConfiguration.cellRightMargin, // CELL_RIGHT_MARGIN, + runGutter: this._layoutConfiguration.cellRunGutter, // CELL_RUN_GUTTER, + }; + } + + computeDiffWebviewOptions() { + return { + outputNodePadding: this._layoutConfiguration.cellOutputPadding, // CELL_OUTPUT_PADDING, + outputNodeLeftPadding: 32, + previewNodePadding: this._layoutConfiguration.markdownPreviewPadding, // MARKDOWN_PREVIEW_PADDING, + leftMargin: 0, + rightMargin: 0, + runGutter: 0 + }; + } } From 5537a8a9c4807608cb552c27020622fc3cae8104 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 18:09:11 -0700 Subject: [PATCH 13/76] dispose notebook options. --- .../contrib/notebook/browser/diff/notebookTextDiffEditor.ts | 1 + .../contrib/notebook/browser/notebookEditorWidget.ts | 1 + src/vs/workbench/contrib/notebook/common/notebookOptions.ts | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 12257d62add..9db388ec10e 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -100,6 +100,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD ) { super(NotebookTextDiffEditor.ID, telemetryService, themeService, storageService); this._notebookOptions = new NotebookOptions(this.configurationService); + this._register(this._notebookOptions); const editorOptions = this.configurationService.getValue('editor'); this._fontInfo = readFontInfo(BareFontInfo.createFromRawSettings(editorOptions, getZoomLevel(), getPixelRatio())); this._revealFirst = true; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index b24ce3d3957..b4a1c2d58a8 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -339,6 +339,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this.useRenderer = !isWeb && !!this.configurationService.getValue(ExperimentalUseMarkdownRenderer) && !accessibilityService.isScreenReaderOptimized(); this._notebookOptions = new NotebookOptions(this.configurationService); + this._register(this._notebookOptions); this._overlayContainer = document.createElement('div'); this.scopedContextKeyService = contextKeyService.createScoped(this._overlayContainer); diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index d0fe5ca3b68..9c6239a79b5 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -251,4 +251,9 @@ export class NotebookOptions { runGutter: 0 }; } + + dispose() { + this._disposables.forEach(d => d.dispose()); + this._disposables = []; + } } From caad0a943f6eb3a8d3d98d48e5de792955992844 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 22:03:54 -0700 Subject: [PATCH 14/76] compute markdown indicator height --- .../notebook/browser/view/renderers/cellRenderer.ts | 9 ++++----- .../workbench/contrib/notebook/common/notebookOptions.ts | 7 +++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index b4ce80acebc..9ebb664546d 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -508,11 +508,10 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR } private updateForLayout(element: MarkdownCellViewModel, templateData: MarkdownCellRenderTemplate): void { - const layoutInfo = this.notebookEditor.notebookOptions.getLayoutConfiguration(); - templateData.focusIndicatorBottom.style.top = `${element.layoutInfo.totalHeight - layoutInfo.bottomCellToolbarGap - layoutInfo.cellBottomMargin}px`; - const focusSideHeight = element.layoutInfo.totalHeight - layoutInfo.bottomCellToolbarGap; - templateData.focusIndicatorLeft.style.height = `${focusSideHeight}px`; - templateData.focusIndicatorRight.style.height = `${focusSideHeight}px`; + const indicatorPostion = this.notebookEditor.notebookOptions.computeIndicatorPosition(element.layoutInfo.totalHeight); + templateData.focusIndicatorBottom.style.top = `${indicatorPostion.bottomIndicatorTop}px`; + templateData.focusIndicatorLeft.style.height = `${indicatorPostion.verticalIndicatorHeight}px`; + templateData.focusIndicatorRight.style.height = `${indicatorPostion.verticalIndicatorHeight}px`; } private updateForHover(element: MarkdownCellViewModel, templateData: MarkdownCellRenderTemplate): void { diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 9c6239a79b5..6a6261310c3 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -252,6 +252,13 @@ export class NotebookOptions { }; } + computeIndicatorPosition(totalHeight: number) { + return { + bottomIndicatorTop: totalHeight - this._layoutConfiguration.bottomCellToolbarGap - this._layoutConfiguration.cellBottomMargin, + verticalIndicatorHeight: totalHeight - this._layoutConfiguration.bottomCellToolbarGap + }; + } + dispose() { this._disposables.forEach(d => d.dispose()); this._disposables = []; From cb8a322e5cd6db6d35742de6bc117a3baeba1c5b Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 11 May 2021 22:04:14 -0700 Subject: [PATCH 15/76] cell editor bg color should not affect toolbar. --- .../notebook/browser/notebookEditorWidget.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index b4a1c2d58a8..4e844150b73 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -2691,17 +2691,20 @@ registerThemingParticipant((theme, collector) => { collector.addRule(`.notebookOverlay .output-show-more-container { background-color: ${containerBackground}; }`); } + const notebookBackground = theme.getColor(editorBackground); + if (notebookBackground) { + collector.addRule(`.notebookOverlay .cell-drag-image .cell-editor-container > div { background: ${notebookBackground} !important; }`); + collector.addRule(`.notebookOverlay .monaco-list-row .cell-title-toolbar { background-color: ${notebookBackground}; }`); + collector.addRule(`.notebookOverlay .monaco-list-row.cell-drag-image { background-color: ${notebookBackground}; }`); + collector.addRule(`.notebookOverlay .cell-bottom-toolbar-container .action-item { background-color: ${notebookBackground} }`); + collector.addRule(`.notebookOverlay .cell-list-top-cell-toolbar-container .action-item { background-color: ${notebookBackground} }`); + } + const editorBackgroundColor = theme.getColor(cellEditorBackground) ?? theme.getColor(editorBackground); if (editorBackgroundColor) { collector.addRule(`.notebookOverlay .cell .monaco-editor-background, - .notebookOverlay .cell .margin-view-overlays, - .notebookOverlay .cell .cell-statusbar-container { background: ${editorBackgroundColor}; }`); - collector.addRule(`.notebookOverlay .cell-drag-image .cell-editor-container > div { background: ${editorBackgroundColor} !important; }`); - - collector.addRule(`.notebookOverlay .monaco-list-row .cell-title-toolbar { background-color: ${editorBackgroundColor}; }`); - collector.addRule(`.notebookOverlay .monaco-list-row.cell-drag-image { background-color: ${editorBackgroundColor}; }`); - collector.addRule(`.notebookOverlay .cell-bottom-toolbar-container .action-item { background-color: ${editorBackgroundColor} }`); - collector.addRule(`.notebookOverlay .cell-list-top-cell-toolbar-container .action-item { background-color: ${editorBackgroundColor} }`); + .notebookOverlay .cell .margin-view-overlays, + .notebookOverlay .cell .cell-statusbar-container { background: ${editorBackgroundColor}; }`); } const cellToolbarSeperator = theme.getColor(CELL_TOOLBAR_SEPERATOR); From 0b3618c6e99d396181198f1bfa78f2204e6f92fd Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 12 May 2021 08:53:18 +0200 Subject: [PATCH 16/76] fix integration test --- .../src/singlefolder-tests/notebook.editor.test.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.editor.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.editor.test.ts index 1a1396d3edf..26f796d3fc8 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.editor.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.editor.test.ts @@ -40,9 +40,7 @@ suite('Notebook Editor', function () { }); - test.skip('showNotebookDocment', async function () { - - const count1 = vscode.notebook.notebookDocuments.length; + test('showNotebookDocment', async function () { const p = utils.asPromise(vscode.notebook.onDidOpenNotebookDocument); const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest'); @@ -53,9 +51,8 @@ suite('Notebook Editor', function () { const event = await p; assert.strictEqual(event.uri.toString(), uri.toString()); - const count2 = vscode.notebook.notebookDocuments.length; - assert.strictEqual(count1 + 1, count2); - + const includes = vscode.notebook.notebookDocuments.includes(editor.document); + assert.strictEqual(true, includes); }); test('notebook editor has viewColumn', async function () { From 0a14a26cd39f0cd9cc5d8511f7117729b1c491af Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 12 May 2021 09:34:21 +0200 Subject: [PATCH 17/76] rename latestExecutionSummary to executionSummary --- .../src/singlefolder-tests/notebook.test.ts | 28 +++++++++---------- src/vs/vscode.proposed.d.ts | 16 +++++++---- .../api/common/extHostNotebookDocument.ts | 2 +- .../api/common/extHostTypeConverters.ts | 2 +- src/vs/workbench/api/common/extHostTypes.ts | 6 ++-- 5 files changed, 29 insertions(+), 25 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts index 76c80cb2810..74ee6bfa705 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts @@ -121,7 +121,7 @@ suite('Notebook API tests', function () { kind: vscode.NotebookCellKind.Code, outputs: [], metadata: new vscode.NotebookCellMetadata().with({ custom: { testCellMetadata: 123 } }), - latestExecutionSummary: { startTime: 10, endTime: 20 } + executionSummary: { startTime: 10, endTime: 20 } }, { value: 'test2', @@ -133,7 +133,7 @@ suite('Notebook API tests', function () { ], { testOutputMetadata: true }) ], - latestExecutionSummary: { executionOrder: 5, success: true }, + executionSummary: { executionOrder: 5, success: true }, metadata: new vscode.NotebookCellMetadata().with({ custom: { testCellMetadata: 456 } }) } ] @@ -478,8 +478,8 @@ suite('Notebook API tests', function () { assert.strictEqual(secondCell!.outputs[0].outputs[0].mime, 'text/plain'); assert.strictEqual(secondCell!.outputs[0].outputs[0].value, 'Hello World'); assert.deepStrictEqual(secondCell!.outputs[0].outputs[0].metadata, { testOutputItemMetadata: true }); - assert.strictEqual(secondCell!.latestExecutionSummary?.executionOrder, 5); - assert.strictEqual(secondCell!.latestExecutionSummary?.success, true); + assert.strictEqual(secondCell!.executionSummary?.executionOrder, 5); + assert.strictEqual(secondCell!.executionSummary?.success, true); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), ''); @@ -1205,30 +1205,30 @@ suite('Notebook API tests', function () { verifyOutputSyncKernel.controller.dispose(); }); - test('latestExecutionSummary', async () => { + test('executionSummary', async () => { const resource = await createRandomNotebookFile(); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); const editor = vscode.window.activeNotebookEditor!; const cell = editor.document.cellAt(0); - assert.strictEqual(cell.latestExecutionSummary?.success, undefined); - assert.strictEqual(cell.latestExecutionSummary?.executionOrder, undefined); + assert.strictEqual(cell.executionSummary?.success, undefined); + assert.strictEqual(cell.executionSummary?.executionOrder, undefined); await vscode.commands.executeCommand('notebook.cell.execute'); assert.strictEqual(cell.outputs.length, 1, 'should execute'); - assert.ok(cell.latestExecutionSummary); - assert.strictEqual(cell.latestExecutionSummary!.success, true); - assert.strictEqual(typeof cell.latestExecutionSummary!.executionOrder, 'number'); + assert.ok(cell.executionSummary); + assert.strictEqual(cell.executionSummary!.success, true); + assert.strictEqual(typeof cell.executionSummary!.executionOrder, 'number'); }); - test('initialize latestExecutionSummary', async () => { + test('initialize executionSummary', async () => { const document = await openRandomNotebookDocument(); const cell = document.cellAt(0); - assert.strictEqual(cell.latestExecutionSummary?.success, undefined); - assert.strictEqual(cell.latestExecutionSummary?.startTime, 10); - assert.strictEqual(cell.latestExecutionSummary?.endTime, 20); + assert.strictEqual(cell.executionSummary?.success, undefined); + assert.strictEqual(cell.executionSummary?.startTime, 10); + assert.strictEqual(cell.executionSummary?.endTime, 20); }); diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 1bfcce4e3fc..51ec435218e 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1071,8 +1071,10 @@ declare module 'vscode' { */ readonly outputs: ReadonlyArray; - // todo@API maybe just executionSummary or lastExecutionSummary? - readonly latestExecutionSummary: NotebookCellExecutionSummary | undefined; + /** + * The most recent {@link NotebookCellExecutionSummary excution summary} for this cell. + */ + readonly executionSummary?: NotebookCellExecutionSummary; } /** @@ -1320,8 +1322,10 @@ declare module 'vscode' { */ metadata?: NotebookCellMetadata; - // todo@API just executionSummary or lastExecutionSummary - latestExecutionSummary?: NotebookCellExecutionSummary; + /** + * The execution summary of this cell data. + */ + executionSummary?: NotebookCellExecutionSummary; /** * Create new cell data. Minimal cell data specifies its kind, its source value, and the @@ -1332,9 +1336,9 @@ declare module 'vscode' { * @param languageId The language identifier of the source value. * @param outputs //TODO@API remove ctor? * @param metadata //TODO@API remove ctor? - * @param latestExecutionSummary //TODO@API remove ctor? + * @param executionSummary //TODO@API remove ctor? */ - constructor(kind: NotebookCellKind, value: string, languageId: string, outputs?: NotebookCellOutput[], metadata?: NotebookCellMetadata, latestExecutionSummary?: NotebookCellExecutionSummary); + constructor(kind: NotebookCellKind, value: string, languageId: string, outputs?: NotebookCellOutput[], metadata?: NotebookCellMetadata, executionSummary?: NotebookCellExecutionSummary); } /** diff --git a/src/vs/workbench/api/common/extHostNotebookDocument.ts b/src/vs/workbench/api/common/extHostNotebookDocument.ts index 58ccef8c010..78d10165bb5 100644 --- a/src/vs/workbench/api/common/extHostNotebookDocument.ts +++ b/src/vs/workbench/api/common/extHostNotebookDocument.ts @@ -87,7 +87,7 @@ export class ExtHostCell { document: data.document, get outputs() { return that._outputs.slice(0); }, get metadata() { return that._metadata; }, - get latestExecutionSummary() { return that._previousResult; } + get executionSummary() { return that._previousResult; } }); } return this._apiCell; diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index a197afac238..505ad95ddbe 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -1494,7 +1494,7 @@ export namespace NotebookCellData { source: data.value, metadata: { ...data.metadata, - ...NotebookCellPreviousExecutionResult.from(data.latestExecutionSummary ?? {}) + ...NotebookCellPreviousExecutionResult.from(data.executionSummary ?? {}) }, outputs: data.outputs ? data.outputs.map(NotebookCellOutput.from) : [] }; diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 5f9140d0621..9f997082238 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -3049,15 +3049,15 @@ export class NotebookCellData { languageId: string; outputs?: NotebookCellOutput[]; metadata?: NotebookCellMetadata; - latestExecutionSummary?: vscode.NotebookCellExecutionSummary; + executionSummary?: vscode.NotebookCellExecutionSummary; - constructor(kind: NotebookCellKind, value: string, languageId: string, outputs?: NotebookCellOutput[], metadata?: NotebookCellMetadata, latestExecutionSummary?: vscode.NotebookCellExecutionSummary) { + constructor(kind: NotebookCellKind, value: string, languageId: string, outputs?: NotebookCellOutput[], metadata?: NotebookCellMetadata, executionSummary?: vscode.NotebookCellExecutionSummary) { this.kind = kind; this.value = value; this.languageId = languageId; this.outputs = outputs ?? []; this.metadata = metadata; - this.latestExecutionSummary = latestExecutionSummary; + this.executionSummary = executionSummary; NotebookCellData.validate(this); } From d8e2bee4b46cfb4b5c5e2a7d598f50bbaa97f00c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 12 May 2021 11:48:42 +0200 Subject: [PATCH 18/76] First cut of special action view item for kernel picker command --- .../notebook/browser/contrib/coreActions.ts | 3 + .../browser/contrib/status/editorStatus.ts | 20 +++-- .../notebook/browser/notebookEditor.ts | 12 +++ .../browser/notebookEditorKernelManager.ts | 3 +- .../browser/notebookKernelActionViewItem.ts | 74 +++++++++++++++++++ 5 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 src/vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem.ts diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 374c3759e3f..0ff295fff63 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -35,6 +35,9 @@ import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/not import { Iterable } from 'vs/base/common/iterator'; import { flatten } from 'vs/base/common/arrays'; +// Kernel Command +export const SELECT_KERNEL_ID = 'notebook.selectKernel'; + // Notebook Commands const EXECUTE_NOTEBOOK_COMMAND_ID = 'notebook.execute'; const CANCEL_NOTEBOOK_COMMAND_ID = 'notebook.cancelExecution'; diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts b/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts index 6907f5bc30c..1a5a3e8224a 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts @@ -5,11 +5,11 @@ import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; -import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; +import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IQuickInputButton, IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; -import { NOTEBOOK_ACTIONS_CATEGORY } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions'; -import { getNotebookEditorFromEditorPane, INotebookEditor, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { NOTEBOOK_ACTIONS_CATEGORY, SELECT_KERNEL_ID } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions'; +import { getNotebookEditorFromEditorPane, INotebookEditor, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry, IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; @@ -26,16 +26,23 @@ import { ILogService } from 'vs/platform/log/common/log'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { HoverProviderRegistry } from 'vs/editor/common/modes'; import { Schemas } from 'vs/base/common/network'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; registerAction2(class extends Action2 { constructor() { super({ - id: 'notebook.selectKernel', + id: SELECT_KERNEL_ID, category: NOTEBOOK_ACTIONS_CATEGORY, title: { value: nls.localize('notebookActions.selectKernel', "Select Notebook Kernel"), original: 'Select Notebook Kernel' }, precondition: NOTEBOOK_IS_ACTIVE_EDITOR, icon: selectKernelIcon, f1: true, + menu: { + id: MenuId.EditorTitle, + when: ContextKeyExpr.and(NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), ContextKeyExpr.equals('config.notebook.experimental.showKernelInEditorTitle', true),), + group: 'navigation', + order: -10 + }, description: { description: nls.localize('notebookActions.selectKernel.args', "Notebook Kernel Args"), args: [ @@ -57,7 +64,6 @@ registerAction2(class extends Action2 { } ] }, - }); } @@ -265,7 +271,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution { text: `$(notebook-kernel-select) ${kernel.label}`, ariaLabel: kernel.label, tooltip: isSuggested ? nls.localize('tooltop', "{0} (suggestion)", tooltip) : tooltip, - command: 'notebook.selectKernel', + command: SELECT_KERNEL_ID, }, 'notebook.selectKernel', nls.localize('notebook.info', "Notebook Kernel Info"), @@ -282,7 +288,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution { { text: nls.localize('kernel.select.label', "Select Kernel"), ariaLabel: nls.localize('kernel.select.label', "Select Kernel"), - command: 'notebook.selectKernel', + command: SELECT_KERNEL_ID, backgroundColor: { id: 'statusBarItem.prominentBackground' } }, 'notebook.selectKernel', diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 940296f98c5..218a8d1bec8 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -29,6 +29,10 @@ import { NotebookEditorOptions, NOTEBOOK_EDITOR_ID } from 'vs/workbench/contrib/ import { IBorrowValue, INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/notebookEditorService'; import { clearMarks, getAndClearMarks, mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance'; import { IFileService } from 'vs/platform/files/common/files'; +import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; +import { IAction } from 'vs/base/common/actions'; +import { SELECT_KERNEL_ID } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions'; +import { NotebooKernelActionViewItem } from 'vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem'; const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState'; @@ -103,6 +107,14 @@ export class NotebookEditor extends EditorPane { return this._rootElement; } + override getActionViewItem(action: IAction): IActionViewItem | undefined { + if (action.id === SELECT_KERNEL_ID) { + // this is being disposed by the consumer + return this.instantiationService.createInstance(NotebooKernelActionViewItem, action, this); + } + return undefined; + } + override getControl(): NotebookEditorWidget | undefined { return this._widget.value; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorKernelManager.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorKernelManager.ts index c4417a2a3c8..033e28d165f 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorKernelManager.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorKernelManager.ts @@ -10,6 +10,7 @@ import { CellKind, INotebookKernel, INotebookTextModel, NotebookCellExecutionSta import { ICommandService } from 'vs/platform/commands/common/commands'; import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust'; +import { SELECT_KERNEL_ID } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions'; export class NotebookEditorKernelManager extends Disposable { @@ -36,7 +37,7 @@ export class NotebookEditorKernelManager extends Disposable { let kernel = this.getSelectedOrSuggestedKernel(notebook); if (!kernel) { - await this._commandService.executeCommand('notebook.selectKernel'); + await this._commandService.executeCommand(SELECT_KERNEL_ID); kernel = this.getSelectedOrSuggestedKernel(notebook); } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem.ts b/src/vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem.ts new file mode 100644 index 00000000000..11345051abc --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem.ts @@ -0,0 +1,74 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; +import { Action, IAction } from 'vs/base/common/actions'; +import { localize } from 'vs/nls'; +import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEditor'; +import { INotebookKernelMatchResult, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; + +export class NotebooKernelActionViewItem extends ActionViewItem { + + constructor( + actualAction: IAction, + private readonly _editor: NotebookEditor, + @INotebookKernelService private readonly _notebookKernelService: INotebookKernelService, + ) { + super( + undefined, + new Action('fakeAction', undefined, undefined, true, (event) => actualAction.run(event)), + { label: true, icon: false } + ); + this._register(_editor.onDidChangeModel(this._update, this)); + } + + override render(container: HTMLElement): void { + this._update(); + super.render(container); + this.label!.style.display = 'inline-block'; + } + + private _update(): void { + const widget = this._editor.getControl(); + if (!widget || !widget.hasModel()) { + this._resetAction(); + return; + } + const notebook = widget.viewModel.notebookDocument; + const info = this._notebookKernelService.getMatchingKernel(notebook); + this._updateActionFromKernelInfo(info); + } + + private _updateActionFromKernelInfo(info: INotebookKernelMatchResult): void { + + if (info.all.length === 0) { + // should not happen - means "bad" context keys + this._resetAction(); + return; + } + + this._action.enabled = true; + const selectedOrSuggested = info.selected ?? info.suggested; + if (selectedOrSuggested) { + // selected or suggested kernel + this._action.label = selectedOrSuggested.label; + this._action.tooltip = selectedOrSuggested.description ?? selectedOrSuggested.detail ?? ''; + if (!info.selected) { + // special UI for selected kernel? + } + + } else { + // many kernels + this._action.label = localize('select', "Select Kernel"); + this._action.tooltip = ''; + } + } + + private _resetAction(): void { + this._action.enabled = false; + this._action.label = ''; + this._action.class = ''; + } +} From b5702a305a848130068880e60ececf3aed6eeddb Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 12 May 2021 13:40:52 +0200 Subject: [PATCH 19/76] mark 'text/x-javascript' as always secure because we only render it --- src/vs/workbench/contrib/notebook/common/notebookCommon.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index e09f29c8652..a8b2fcaf6f1 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -549,7 +549,7 @@ const _mimeTypeInfo = new Map([ ['text/html', { supportedByCore: true }], ['image/svg+xml', { supportedByCore: true }], ['image/jpeg', { supportedByCore: true }], - ['text/x-javascript', { supportedByCore: true }], + ['text/x-javascript', { alwaysSecure: true, supportedByCore: true }], // secure because rendered as text, not executed ['application/x.notebook.error-traceback', { alwaysSecure: true, supportedByCore: true }], ['application/x.notebook.stream', { alwaysSecure: true, supportedByCore: true, mergeable: true }], ['application/x.notebook.stdout', { alwaysSecure: true, supportedByCore: true, mergeable: true }], @@ -888,4 +888,3 @@ export class NotebookWorkingCopyTypeIdentifier { return undefined; } } - From 096d9cde61584800443c7e54b6cdf2622ee3cf2d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 12 May 2021 14:03:54 +0200 Subject: [PATCH 20/76] fix https://github.com/microsoft/vscode/issues/123665 --- .../browser/view/output/outputRenderer.ts | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/outputRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/output/outputRenderer.ts index 9aa00edf264..14ce25b10ba 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/output/outputRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/output/outputRenderer.ts @@ -9,36 +9,35 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { ICellOutputViewModel, ICommonNotebookEditor, IOutputTransformContribution, IRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { URI } from 'vs/base/common/uri'; import { Disposable } from 'vs/base/common/lifecycle'; +import { localize } from 'vs/nls'; export class OutputRenderer extends Disposable { - protected _contributions: { [key: string]: IOutputTransformContribution; }; - protected _renderers: IOutputTransformContribution[]; - private _richMimeTypeRenderers = new Map(); + + private readonly _richMimeTypeRenderers = new Map(); constructor( notebookEditor: ICommonNotebookEditor, private readonly instantiationService: IInstantiationService ) { super(); - - this._contributions = {}; - this._renderers = []; - - const contributions = NotebookRegistry.getOutputTransformContributions(); - - for (const desc of contributions) { + for (const desc of NotebookRegistry.getOutputTransformContributions()) { try { const contribution = this.instantiationService.createInstance(desc.ctor, notebookEditor); - this._contributions[desc.id] = contribution; contribution.getMimetypes().forEach(mimetype => { this._richMimeTypeRenderers.set(mimetype, contribution); }); + this._register(contribution); } catch (err) { onUnexpectedError(err); } } } + override dispose(): void { + super.dispose(); + this._richMimeTypeRenderers.clear(); + } + getContribution(preferredMimeType: string | undefined): IOutputTransformContribution | undefined { if (preferredMimeType) { return this._richMimeTypeRenderers.get(preferredMimeType); @@ -47,17 +46,16 @@ export class OutputRenderer extends Disposable { return undefined; } - renderNoop(viewModel: ICellOutputViewModel, container: HTMLElement): IRenderOutput { + private _renderNoop(viewModel: ICellOutputViewModel, container: HTMLElement): IRenderOutput { const contentNode = document.createElement('p'); - - contentNode.innerText = `No renderer could be found for output.`; + contentNode.innerText = localize('empty', "No renderer could be found for output."); container.appendChild(contentNode); return { type: RenderOutputType.Mainframe }; } render(viewModel: ICellOutputViewModel, container: HTMLElement, preferredMimeType: string | undefined, notebookUri: URI): IRenderOutput { if (!viewModel.model.outputs.length) { - return this.renderNoop(viewModel, container); + return this._renderNoop(viewModel, container); } if (!preferredMimeType || !this._richMimeTypeRenderers.has(preferredMimeType)) { @@ -67,9 +65,9 @@ export class OutputRenderer extends Disposable { const mimeTypesMessage = mimeTypes.join(', '); if (preferredMimeType) { - contentNode.innerText = `No renderer could be found for MIME type: ${preferredMimeType}`; + contentNode.innerText = localize('noRenderer.1', "No renderer could be found for MIME type: {0}", preferredMimeType); } else { - contentNode.innerText = `No renderer could be found for output. It has the following MIME types: ${mimeTypesMessage}`; + contentNode.innerText = localize('noRenderer.2', "No renderer could be found for output. It has the following MIME types: {0}", mimeTypesMessage); } container.appendChild(contentNode); @@ -82,13 +80,7 @@ export class OutputRenderer extends Disposable { if (items.length && renderer) { return renderer.render(viewModel, items, container, notebookUri); } else { - return this.renderNoop(viewModel, container); + return this._renderNoop(viewModel, container); } } - - override dispose() { - this._contributions = {}; - this._renderers = []; - this._richMimeTypeRenderers.clear(); - } } From 9553ccbe6ed0224f2168c6fe503d2f20c55c1825 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 12 May 2021 14:20:53 +0200 Subject: [PATCH 21/76] workaround #123676 --- .../browser/parts/editor/editorControl.ts | 24 +++++++++---------- .../browser/parts/editor/editorPane.test.ts | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorControl.ts b/src/vs/workbench/browser/parts/editor/editorControl.ts index c063c541e47..739c5f7ec87 100644 --- a/src/vs/workbench/browser/parts/editor/editorControl.ts +++ b/src/vs/workbench/browser/parts/editor/editorControl.ts @@ -16,7 +16,7 @@ import { IEditorGroupView, DEFAULT_EDITOR_MIN_DIMENSIONS, DEFAULT_EDITOR_MAX_DIM import { Emitter } from 'vs/base/common/event'; import { assertIsDefined } from 'vs/base/common/types'; import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust'; -import { WorkspaceTrustRequiredEditor } from 'vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor'; +// import { WorkspaceTrustRequiredEditor } from 'vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor'; export interface IOpenEditorResult { readonly editorPane: EditorPane; @@ -80,7 +80,7 @@ export class EditorControl extends Disposable { async openEditor(editor: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext = Object.create(null)): Promise { // Editor descriptor - const descriptor = await this.resolveEditorDescriptor(editor); + const descriptor = assertIsDefined(this.editorsRegistry.getEditor(editor)); // Editor pane const editorPane = this.doShowEditorPane(descriptor); @@ -90,18 +90,18 @@ export class EditorControl extends Disposable { return { editorPane, editorChanged }; } - private async resolveEditorDescriptor(editor: EditorInput): Promise { - const editorRequiresTrust = await editor.requiresWorkspaceTrust(); - const editorBlockedByTrust = editorRequiresTrust && !this.workspaceTrustService.isWorkpaceTrusted(); + // private async resolveEditorDescriptor(editor: EditorInput): Promise { + // const editorRequiresTrust = await editor.requiresWorkspaceTrust(); + // const editorBlockedByTrust = editorRequiresTrust && !this.workspaceTrustService.isWorkpaceTrusted(); - // Workspace trust: if an editor signals it needs workspace trust - // but the current workspace is untrusted, we fallback to a generic - // editor descriptor to indicate this an do NOT load the registered - // editor. - const descriptor = editorBlockedByTrust ? WorkspaceTrustRequiredEditor.DESCRIPTOR : this.editorsRegistry.getEditor(editor); + // // Workspace trust: if an editor signals it needs workspace trust + // // but the current workspace is untrusted, we fallback to a generic + // // editor descriptor to indicate this an do NOT load the registered + // // editor. + // const descriptor = editorBlockedByTrust ? WorkspaceTrustRequiredEditor.DESCRIPTOR : this.editorsRegistry.getEditor(editor); - return assertIsDefined(descriptor); - } + // return assertIsDefined(descriptor); + // } private doShowEditorPane(descriptor: IEditorDescriptor): EditorPane { diff --git a/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts b/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts index 25732e692bc..a3a7498b533 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts @@ -400,7 +400,7 @@ suite('Workbench EditorPane', () => { assert.ok(!res); }); - test('WorkspaceTrustRequiredEditor', async function () { + test.skip('WorkspaceTrustRequiredEditor', async function () { class TrustRequiredTestEditor extends EditorPane { constructor(@ITelemetryService telemetryService: ITelemetryService) { super('TestEditor', NullTelemetryService, NullThemeService, new TestStorageService()); From 64e707842e612b18edb346a676808bad614c30ce Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 12 May 2021 14:21:20 +0200 Subject: [PATCH 22/76] workaround for https://github.com/microsoft/vscode/issues/123667 --- .../view/output/transforms/richTransform.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts index d9e5bd8ee35..dcd4c1d0f7e 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as DOM from 'vs/base/browser/dom'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, dispose } from 'vs/base/common/lifecycle'; import { dirname } from 'vs/base/common/resources'; import { isArray } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; @@ -120,6 +120,8 @@ class CodeRendererContrib extends Disposable implements IOutputRendererContribut return ['text/x-javascript']; } + private readonly _cellDisposables = new Map(); + constructor( public notebookEditor: ICommonNotebookEditor, @IInstantiationService private readonly instantiationService: IInstantiationService, @@ -129,7 +131,19 @@ class CodeRendererContrib extends Disposable implements IOutputRendererContribut super(); } + override dispose(): void { + dispose(this._cellDisposables.values()); + this._cellDisposables.clear(); + super.dispose(); + } + render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput { + + let cellDisposables = this._cellDisposables.get(output.cellViewModel.handle); + cellDisposables?.dispose(); + cellDisposables = new DisposableStore(); + this._cellDisposables.set(output.cellViewModel.handle, cellDisposables); + const str = items.map(item => getStringValue(item.value)).join(''); const editor = this.instantiationService.createInstance(CodeEditorWidget, container, { ...getOutputSimpleEditorOptions(), @@ -155,6 +169,9 @@ class CodeRendererContrib extends Disposable implements IOutputRendererContribut width }); + cellDisposables.add(editor); + cellDisposables.add(textModel); + container.style.height = `${height + 8}px`; return { type: RenderOutputType.Mainframe }; From 3c6377db03084e199cb60ddfdf5847f072746be7 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 12 May 2021 14:43:16 +0200 Subject: [PATCH 23/76] Cannot drop a *. ply file into the window (fix #123496) --- .../services/editor/browser/editorService.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 9b1b454d2f9..d4993b56534 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -606,7 +606,10 @@ export class EditorService extends Disposable implements EditorServiceImpl { return undefined; // no editor was picked or registered for the identifier } - return (resolvedInputWithOptionsAndGroup.group ?? resolvedGroup).openEditor(resolvedInputWithOptionsAndGroup.editor, resolvedInputWithOptionsAndGroup.options ?? resolvedOptions); + return (resolvedInputWithOptionsAndGroup.group ?? resolvedGroup).openEditor( + resolvedInputWithOptionsAndGroup.editor, + this.toOptions(resolvedInputWithOptionsAndGroup.options) ?? resolvedOptions + ); } // Override handling: ask providers to override @@ -621,7 +624,10 @@ export class EditorService extends Disposable implements EditorServiceImpl { return override; } } else { - return (resolvedInputWithOptionsAndGroup.group ?? resolvedGroup).openEditor(resolvedInputWithOptionsAndGroup.editor, resolvedInputWithOptionsAndGroup.options ?? resolvedOptions); + return (resolvedInputWithOptionsAndGroup.group ?? resolvedGroup).openEditor( + resolvedInputWithOptionsAndGroup.editor, + this.toOptions(resolvedInputWithOptionsAndGroup.options) ?? resolvedOptions + ); } } @@ -833,7 +839,10 @@ export class EditorService extends Disposable implements EditorServiceImpl { mapGroupToEditors.set(targetGroup, targetGroupEditors); } - targetGroupEditors.push(editorOverride ?? { editor, options }); + targetGroupEditors.push(editorOverride ? + { editor: editorOverride.editor, options: this.toOptions(editorOverride.options) } : + { editor, options } + ); } } From baa0a2890e72aef3881c2cc9e7ed39b6e1dd9a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 12 May 2021 14:51:10 +0200 Subject: [PATCH 24/76] web api: expose uriScheme and openUri --- src/vs/workbench/browser/web.main.ts | 7 +++++++ src/vs/workbench/workbench.web.api.ts | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index d5bf2097591..e658791524a 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -63,6 +63,7 @@ import { ITimerService } from 'vs/workbench/services/timer/browser/timerService' import { WorkspaceTrustManagementService } from 'vs/workbench/services/workspaces/common/workspaceTrust'; import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust'; import { HTMLFileSystemProvider } from 'vs/platform/files/browser/htmlFileSystemProvider'; +import { IOpenerService } from 'vs/platform/opener/common/opener'; class BrowserMain extends Disposable { @@ -106,16 +107,22 @@ class BrowserMain extends Disposable { const commandService = accessor.get(ICommandService); const lifecycleService = accessor.get(ILifecycleService); const timerService = accessor.get(ITimerService); + const openerService = accessor.get(IOpenerService); + const productService = accessor.get(IProductService); return { commands: { executeCommand: (command, ...args) => commandService.executeCommand(command, ...args) }, env: { + uriScheme: productService.urlProtocol, async retrievePerformanceMarks() { await timerService.whenReady(); return timerService.getPerformanceMarks(); + }, + async openUri(uri: URI): Promise { + return openerService.open(uri, {}); } }, shutdown: () => lifecycleService.shutdown() diff --git a/src/vs/workbench/workbench.web.api.ts b/src/vs/workbench/workbench.web.api.ts index 84d1dd886fc..0605863599d 100644 --- a/src/vs/workbench/workbench.web.api.ts +++ b/src/vs/workbench/workbench.web.api.ts @@ -457,10 +457,12 @@ interface IWorkbench { } env: { + readonly uriScheme: string; /** * @see [retrievePerformanceMarks](#commands.retrievePerformanceMarks) */ retrievePerformanceMarks(): Promise<[string, readonly IPerformanceMark[]][]>; + openUri(uri: URI): Promise; } /** @@ -560,6 +562,16 @@ namespace env { return workbench.env.retrievePerformanceMarks(); } + + export async function getUriScheme(): Promise { + const workbench = await workbenchPromise; + return workbench.env.uriScheme; + } + + export async function openUri(target: URI): Promise { + const workbench = await workbenchPromise; + return workbench.env.openUri(target); + } } export { From 1379ca20335263601e3854d3b28e11b7d8a99e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 12 May 2021 14:51:52 +0200 Subject: [PATCH 25/76] extension url handler: fix missing gallery --- .../services/extensions/browser/extensionUrlHandler.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts index 129ab322e21..0857b40a512 100644 --- a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts +++ b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts @@ -8,7 +8,7 @@ import { IDisposable, toDisposable, combinedDisposable } from 'vs/base/common/li import { URI } from 'vs/base/common/uri'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService, IGalleryExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IWorkbenchExtensionEnablementService, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { createDecorator, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -255,7 +255,13 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { // Extension is not installed else { - const galleryExtension = await this.galleryService.getCompatibleExtension(extensionIdentifier); + let galleryExtension: IGalleryExtension | undefined; + + try { + galleryExtension = await this.galleryService.getCompatibleExtension(extensionIdentifier) ?? undefined; + } catch (err) { + return; + } if (!galleryExtension) { return; From f9dc69696058aa9a155424a437f9c4075974e853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 12 May 2021 14:52:04 +0200 Subject: [PATCH 26/76] browser url service: hook up to opener service --- .../services/url/browser/urlService.ts | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/services/url/browser/urlService.ts b/src/vs/workbench/services/url/browser/urlService.ts index bb54701dd47..d355196786e 100644 --- a/src/vs/workbench/services/url/browser/urlService.ts +++ b/src/vs/workbench/services/url/browser/urlService.ts @@ -9,6 +9,8 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { AbstractURLService } from 'vs/platform/url/common/urlService'; import { Event } from 'vs/base/common/event'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { IOpenerService, IOpener, OpenExternalOptions, OpenInternalOptions, matchesScheme } from 'vs/platform/opener/common/opener'; +import { IProductService } from 'vs/platform/product/common/productService'; export interface IURLCallbackProvider { @@ -36,24 +38,44 @@ export interface IURLCallbackProvider { create(options?: Partial): URI; } +class BrowserURLOpener implements IOpener { + + constructor( + private urlService: IURLService, + private productService: IProductService + ) { } + + async open(resource: string | URI, options?: OpenInternalOptions | OpenExternalOptions): Promise { + if (!matchesScheme(resource, this.productService.urlProtocol)) { + return false; + } + + if (typeof resource === 'string') { + resource = URI.parse(resource); + } + + return this.urlService.open(resource, { trusted: true }); + } +} + export class BrowserURLService extends AbstractURLService { private provider: IURLCallbackProvider | undefined; constructor( - @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService + @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, + @IOpenerService openerService: IOpenerService, + @IProductService productService: IProductService ) { super(); this.provider = environmentService.options?.urlCallbackProvider; - this.registerListeners(); - } - - private registerListeners(): void { if (this.provider) { this._register(this.provider.onCallback(uri => this.open(uri, { trusted: true }))); } + + this._register(openerService.registerOpener(new BrowserURLOpener(this, productService))); } create(options?: Partial): URI { From 3146c54bf38e1eb95ead75a575679615f00531f6 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 12 May 2021 14:52:17 +0200 Subject: [PATCH 27/76] Use dialog for change local port mismatch Part of microsoft/vscode-remote-release#4958 --- src/vs/workbench/contrib/remote/browser/tunnelView.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index e84b9c74737..c0a0d365779 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -51,6 +51,7 @@ import { IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent'; import { IHoverDelegateOptions } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate'; import { IHoverService } from 'vs/workbench/services/hover/browser/hover'; import { STATUS_BAR_HOST_NAME_BACKGROUND } from 'vs/workbench/common/theme'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; export const forwardedPortsViewEnabled = new RawContextKey('forwardedPortsViewEnabled', false, nls.localize('tunnel.forwardedPortsViewEnabled', "Whether the Ports view is enabled.")); @@ -1318,7 +1319,7 @@ namespace ChangeLocalPortAction { export function handler(): ICommandHandler { return async (accessor, arg) => { const remoteExplorerService = accessor.get(IRemoteExplorerService); - const notificationService = accessor.get(INotificationService); + const dialogService = accessor.get(IDialogService); const tunnelService = accessor.get(ITunnelService); const context = (arg !== undefined || arg instanceof TunnelItem) ? arg : accessor.get(IContextKeyService).getContextKeyValue(TunnelViewSelectionKeyName); if (context instanceof TunnelItem) { @@ -1330,7 +1331,9 @@ namespace ChangeLocalPortAction { const numberValue = Number(value); const newForward = await remoteExplorerService.forward({ host: context.remoteHost, port: context.remotePort }, numberValue, context.name, undefined, true); if (newForward && newForward.tunnelLocalPort !== numberValue) { - notificationService.warn(nls.localize('remote.tunnel.changeLocalPortNumber', "The local port {0} is not available. Port number {1} has been used instead", value, newForward.tunnelLocalPort ?? newForward.localAddress)); + dialogService.show(Severity.Info, + nls.localize('remote.tunnel.changeLocalPortNumber', "The local port {0} is not available.\n\nThis usually happens when is already another process using port {0}.\n\nPort number {1} has been used instead.", value, newForward.tunnelLocalPort ?? newForward.localAddress), + [nls.localize('remote.tunnel.changeLocalPortNumber.Ok', "Ok")]); } } }, From d13f5feb43d153211c2f82de1ffe0e74f5e467c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 12 May 2021 15:11:07 +0200 Subject: [PATCH 28/76] fix npe --- .../services/extensions/browser/extensionUrlHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts index 0857b40a512..6c46aa16113 100644 --- a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts +++ b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts @@ -283,7 +283,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { await this.progressService.withProgress({ location: ProgressLocation.Notification, title: localize('Installing', "Installing Extension '{0}'...", galleryExtension.displayName || galleryExtension.name) - }, () => this.extensionManagementService.installFromGallery(galleryExtension)); + }, () => this.extensionManagementService.installFromGallery(galleryExtension!)); this.notificationService.prompt( Severity.Info, From fd529498f0e70feeb75730a5a155d5d878cb2750 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 12 May 2021 15:20:35 +0200 Subject: [PATCH 29/76] Typos in tunnelView string Part of microsoft/vscode-remote-release#4958 --- src/vs/workbench/contrib/remote/browser/tunnelView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index c0a0d365779..a491a479212 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -1332,7 +1332,7 @@ namespace ChangeLocalPortAction { const newForward = await remoteExplorerService.forward({ host: context.remoteHost, port: context.remotePort }, numberValue, context.name, undefined, true); if (newForward && newForward.tunnelLocalPort !== numberValue) { dialogService.show(Severity.Info, - nls.localize('remote.tunnel.changeLocalPortNumber', "The local port {0} is not available.\n\nThis usually happens when is already another process using port {0}.\n\nPort number {1} has been used instead.", value, newForward.tunnelLocalPort ?? newForward.localAddress), + nls.localize('remote.tunnel.changeLocalPortNumber', "The local port {0} is not available.\n\nThis usually happens when there is already another process using port {0}.\n\nPort number {1} has been used instead.", value, newForward.tunnelLocalPort ?? newForward.localAddress), [nls.localize('remote.tunnel.changeLocalPortNumber.Ok', "Ok")]); } } From 608d03bf72bd60e38d781754c1935d7f7ae072c5 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 10 May 2021 16:23:16 +0200 Subject: [PATCH 30/76] Fixes microsoft/monaco-editor#2409 --- src/vs/base/common/platform.ts | 2 +- src/vs/base/common/process.ts | 2 +- src/vs/platform/product/common/product.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts index 5bbdbe95df0..512775eaddc 100644 --- a/src/vs/base/common/platform.ts +++ b/src/vs/base/common/platform.ts @@ -53,7 +53,7 @@ declare const self: unknown; export const globals: any = (typeof self === 'object' ? self : typeof global === 'object' ? global : {}); let nodeProcess: INodeProcess | undefined = undefined; -if (typeof globals.vscode !== 'undefined') { +if (typeof globals.vscode !== 'undefined' && typeof globals.vscode.process !== 'undefined') { // Native environment (sandboxed) nodeProcess = globals.vscode.process; } else if (typeof process !== 'undefined') { diff --git a/src/vs/base/common/process.ts b/src/vs/base/common/process.ts index 2df6dd5df2f..6c4b1f407d5 100644 --- a/src/vs/base/common/process.ts +++ b/src/vs/base/common/process.ts @@ -9,7 +9,7 @@ let safeProcess: INodeProcess & { nextTick: (callback: (...args: any[]) => void) declare const process: INodeProcess; // Native sandbox environment -if (typeof globals.vscode !== 'undefined') { +if (typeof globals.vscode !== 'undefined' && typeof globals.vscode.process !== 'undefined') { const sandboxProcess: INodeProcess = globals.vscode.process; safeProcess = { get platform() { return sandboxProcess.platform; }, diff --git a/src/vs/platform/product/common/product.ts b/src/vs/platform/product/common/product.ts index 11a5cdd663a..28e36704128 100644 --- a/src/vs/platform/product/common/product.ts +++ b/src/vs/platform/product/common/product.ts @@ -13,7 +13,7 @@ import { ISandboxConfiguration } from 'vs/base/parts/sandbox/common/sandboxTypes let product: IProductConfiguration; // Native sandbox environment -if (typeof globals.vscode !== 'undefined') { +if (typeof globals.vscode !== 'undefined' && typeof globals.vscode.context !== 'undefined') { const configuration: ISandboxConfiguration | undefined = globals.vscode.context.configuration(); if (configuration) { product = configuration.product; From 5ac3eaeaf6a157b4e31b07dcd11930e4273758c3 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 11 May 2021 11:54:29 +0200 Subject: [PATCH 31/76] Fixes microsoft/monaco-editor#2396: Add an option to opt out of the usage of shadow dom inside the editor --- src/vs/editor/common/config/editorOptions.ts | 8 ++++ .../common/standalone/standaloneEnums.ts | 35 ++++++++-------- .../contrib/codeAction/codeActionMenu.ts | 5 ++- .../editor/contrib/contextmenu/contextmenu.ts | 4 +- src/vs/monaco.d.ts | 40 +++++++++++-------- 5 files changed, 56 insertions(+), 36 deletions(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 4eb14e26c69..e54089a3aed 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -638,6 +638,10 @@ export interface IEditorOptions { * Control the behavior and rendering of the inline hints. */ inlayHints?: IEditorInlayHintsOptions; + /** + * Control if the editor should use shadow DOM. + */ + useShadowDOM?: boolean; } /** @@ -3845,6 +3849,7 @@ export const enum EditorOption { tabCompletion, tabIndex, unusualLineTerminators, + useShadowDOM, useTabStops, wordSeparators, wordWrap, @@ -4460,6 +4465,9 @@ export const EditorOptions = { description: nls.localize('unusualLineTerminators', "Remove unusual line terminators that might cause problems.") } )), + useShadowDOM: register(new EditorBooleanOption( + EditorOption.useShadowDOM, 'useShadowDOM', true + )), useTabStops: register(new EditorBooleanOption( EditorOption.useTabStops, 'useTabStops', true, { description: nls.localize('useTabStops', "Inserting and deleting whitespace follows tab stops.") } diff --git a/src/vs/editor/common/standalone/standaloneEnums.ts b/src/vs/editor/common/standalone/standaloneEnums.ts index 6093e74955f..004d924d1fc 100644 --- a/src/vs/editor/common/standalone/standaloneEnums.ts +++ b/src/vs/editor/common/standalone/standaloneEnums.ts @@ -278,23 +278,24 @@ export enum EditorOption { tabCompletion = 108, tabIndex = 109, unusualLineTerminators = 110, - useTabStops = 111, - wordSeparators = 112, - wordWrap = 113, - wordWrapBreakAfterCharacters = 114, - wordWrapBreakBeforeCharacters = 115, - wordWrapColumn = 116, - wordWrapOverride1 = 117, - wordWrapOverride2 = 118, - wrappingIndent = 119, - wrappingStrategy = 120, - showDeprecated = 121, - inlayHints = 122, - editorClassName = 123, - pixelRatio = 124, - tabFocusMode = 125, - layoutInfo = 126, - wrappingInfo = 127 + useShadowDOM = 111, + useTabStops = 112, + wordSeparators = 113, + wordWrap = 114, + wordWrapBreakAfterCharacters = 115, + wordWrapBreakBeforeCharacters = 116, + wordWrapColumn = 117, + wordWrapOverride1 = 118, + wordWrapOverride2 = 119, + wrappingIndent = 120, + wrappingStrategy = 121, + showDeprecated = 122, + inlayHints = 123, + editorClassName = 124, + pixelRatio = 125, + tabFocusMode = 126, + layoutInfo = 127, + wrappingInfo = 128 } /** diff --git a/src/vs/editor/contrib/codeAction/codeActionMenu.ts b/src/vs/editor/contrib/codeAction/codeActionMenu.ts index e4a05011d01..d4b830000f0 100644 --- a/src/vs/editor/contrib/codeAction/codeActionMenu.ts +++ b/src/vs/editor/contrib/codeAction/codeActionMenu.ts @@ -11,6 +11,7 @@ import { ResolvedKeybinding } from 'vs/base/common/keyCodes'; import { Lazy } from 'vs/base/common/lazy'; import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { IPosition, Position } from 'vs/editor/common/core/position'; import { ScrollType } from 'vs/editor/common/editorCommon'; import { CodeAction, CodeActionProviderRegistry, Command } from 'vs/editor/common/modes'; @@ -92,8 +93,10 @@ export class CodeActionMenu extends Disposable { const anchor = Position.isIPosition(at) ? this._toCoords(at) : at || { x: 0, y: 0 }; const resolver = this._keybindingResolver.getResolver(); + const useShadowDOM = this._editor.getOption(EditorOption.useShadowDOM); + this._contextMenuService.showContextMenu({ - domForShadowRoot: this._editor.getDomNode()!, + domForShadowRoot: useShadowDOM ? this._editor.getDomNode()! : undefined, getAnchor: () => anchor, getActions: () => menuActions, onHide: () => { diff --git a/src/vs/editor/contrib/contextmenu/contextmenu.ts b/src/vs/editor/contrib/contextmenu/contextmenu.ts index 5c95f58c85f..ace4b1b8d3e 100644 --- a/src/vs/editor/contrib/contextmenu/contextmenu.ts +++ b/src/vs/editor/contrib/contextmenu/contextmenu.ts @@ -209,10 +209,12 @@ export class ContextMenuController implements IEditorContribution { anchor = { x: posx, y: posy }; } + const useShadowDOM = this._editor.getOption(EditorOption.useShadowDOM); + // Show menu this._contextMenuIsBeingShownCount++; this._contextMenuService.showContextMenu({ - domForShadowRoot: this._editor.getDomNode(), + domForShadowRoot: useShadowDOM ? this._editor.getDomNode() : undefined, getAnchor: () => anchor!, diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 9773af510f4..3a5584eed05 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -3220,6 +3220,10 @@ declare namespace monaco.editor { * Control the behavior and rendering of the inline hints. */ inlayHints?: IEditorInlayHintsOptions; + /** + * Control if the editor should use shadow DOM. + */ + useShadowDOM?: boolean; } /** @@ -4094,23 +4098,24 @@ declare namespace monaco.editor { tabCompletion = 108, tabIndex = 109, unusualLineTerminators = 110, - useTabStops = 111, - wordSeparators = 112, - wordWrap = 113, - wordWrapBreakAfterCharacters = 114, - wordWrapBreakBeforeCharacters = 115, - wordWrapColumn = 116, - wordWrapOverride1 = 117, - wordWrapOverride2 = 118, - wrappingIndent = 119, - wrappingStrategy = 120, - showDeprecated = 121, - inlayHints = 122, - editorClassName = 123, - pixelRatio = 124, - tabFocusMode = 125, - layoutInfo = 126, - wrappingInfo = 127 + useShadowDOM = 111, + useTabStops = 112, + wordSeparators = 113, + wordWrap = 114, + wordWrapBreakAfterCharacters = 115, + wordWrapBreakBeforeCharacters = 116, + wordWrapColumn = 117, + wordWrapOverride1 = 118, + wordWrapOverride2 = 119, + wrappingIndent = 120, + wrappingStrategy = 121, + showDeprecated = 122, + inlayHints = 123, + editorClassName = 124, + pixelRatio = 125, + tabFocusMode = 126, + layoutInfo = 127, + wrappingInfo = 128 } export const EditorOptions: { acceptSuggestionOnCommitCharacter: IEditorOption; @@ -4226,6 +4231,7 @@ declare namespace monaco.editor { tabCompletion: IEditorOption; tabIndex: IEditorOption; unusualLineTerminators: IEditorOption; + useShadowDOM: IEditorOption; useTabStops: IEditorOption; wordSeparators: IEditorOption; wordWrap: IEditorOption; From 51803eabffdcd4cf31784bce6008c295f2626d42 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 11 May 2021 14:11:41 +0200 Subject: [PATCH 32/76] Expose `ITextModel.isAttachedToEditor()` and `ITextModel.onDidChangeAttached` --- src/vs/editor/common/model.ts | 2 -- src/vs/monaco.d.ts | 9 +++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index cbcaacd273d..cbe55b06871 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -1220,7 +1220,6 @@ export interface ITextModel { /** * An event emitted when the model has been attached to the first editor or detached from the last editor. * @event - * @internal */ onDidChangeAttached(listener: () => void): IDisposable; /** @@ -1247,7 +1246,6 @@ export interface ITextModel { /** * Returns if this model is attached to an editor or not. - * @internal */ isAttachedToEditor(): boolean; diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 3a5584eed05..df444e3dce3 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -1983,6 +1983,11 @@ declare namespace monaco.editor { * @event */ onDidChangeLanguageConfiguration(listener: (e: IModelLanguageConfigurationChangedEvent) => void): IDisposable; + /** + * An event emitted when the model has been attached to the first editor or detached from the last editor. + * @event + */ + onDidChangeAttached(listener: () => void): IDisposable; /** * An event emitted right before disposing the model. * @event @@ -1993,6 +1998,10 @@ declare namespace monaco.editor { * and make all necessary clean-up to release this object to the GC. */ dispose(): void; + /** + * Returns if this model is attached to an editor or not. + */ + isAttachedToEditor(): boolean; } /** From 80308b93d9da08e88a1544beeeb97e112cedb8a9 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 11 May 2021 14:34:11 +0200 Subject: [PATCH 33/76] Fix typo --- src/vs/editor/common/config/editorOptions.ts | 2 +- src/vs/monaco.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index e54089a3aed..ffd74758a35 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -383,7 +383,7 @@ export interface IEditorOptions { */ suggest?: ISuggestOptions; /** - * Smart select opptions; + * Smart select options. */ smartSelect?: ISmartSelectOptions; /** diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index df444e3dce3..8128cb36216 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2974,7 +2974,7 @@ declare namespace monaco.editor { */ suggest?: ISuggestOptions; /** - * Smart select opptions; + * Smart select options. */ smartSelect?: ISmartSelectOptions; /** From 579cf91f0a07f0f2b30ea37bf67f4bdc0a84c8e5 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 11 May 2021 14:57:50 +0200 Subject: [PATCH 34/76] Fixes microsoft/monaco-editor#2474: Use 'noopener' when calling window.open --- src/vs/base/browser/dom.ts | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index e5b9492f3c0..c43adcf92bc 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -1186,21 +1186,15 @@ export function computeScreenAwareSize(cssPx: number): number { * See https://mathiasbynens.github.io/rel-noopener/ */ export function windowOpenNoOpener(url: string): boolean { - if (browser.isElectron || browser.isEdgeLegacyWebView) { - // In VSCode, window.open() always returns null... - // The same is true for a WebView (see https://github.com/microsoft/monaco-editor/issues/628) - // Also call directly window.open in sandboxed Electron (see https://github.com/microsoft/monaco-editor/issues/2220) - window.open(url); + // By using 'noopener' in the windowFeatures argument, the newly created window will + // not be able to use window.opener to reach back to the current page. + // See https://stackoverflow.com/a/46958731 + // See https://developer.mozilla.org/en-US/docs/Web/API/Window/open#noopener + const newTab = window.open(url, '_blank', 'noopener'); + if (newTab) { return true; - } else { - let newTab = window.open(); - if (newTab) { - (newTab as any).opener = null; - newTab.location.href = url; - return true; - } - return false; } + return false; } export function animate(fn: () => void): IDisposable { From 0a2f87623d5f5aa96662fc34130549b03b48f421 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 12 May 2021 14:46:16 +0200 Subject: [PATCH 35/76] Restore behavior of `BrowserWindow.setupOpenHandlers` (see microsoft/monaco-editor#2474) --- src/vs/base/browser/dom.ts | 30 ++++++++++++++++++++++++++---- src/vs/workbench/browser/window.ts | 4 ++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index c43adcf92bc..63a8ce803cf 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -1179,19 +1179,41 @@ export function computeScreenAwareSize(cssPx: number): number { } /** + * Open safely a new window. This is the best way to do so, but you cannot tell + * if the window was opened or if it was blocked by the brower's popup blocker. + * If you want to tell if the browser blocked the new window, use `windowOpenNoOpenerWithSuccess`. + * * See https://github.com/microsoft/monaco-editor/issues/601 * To protect against malicious code in the linked site, particularly phishing attempts, * the window.opener should be set to null to prevent the linked site from having access * to change the location of the current page. * See https://mathiasbynens.github.io/rel-noopener/ */ -export function windowOpenNoOpener(url: string): boolean { - // By using 'noopener' in the windowFeatures argument, the newly created window will - // not be able to use window.opener to reach back to the current page. +export function windowOpenNoOpener(url: string): void { + // By using 'noopener' in the `windowFeatures` argument, the newly created window will + // not be able to use `window.opener` to reach back to the current page. // See https://stackoverflow.com/a/46958731 // See https://developer.mozilla.org/en-US/docs/Web/API/Window/open#noopener - const newTab = window.open(url, '_blank', 'noopener'); + // However, this also doesn't allow us to realize if the browser blocked + // the creation of the window. + window.open(url, '_blank', 'noopener'); +} + +/** + * Open safely a new window. This technique is not appropiate in certain contexts, + * like for example when the JS context is executing inside a sandboxed iframe. + * If it is not necessary to know if the browser blocked the new window, use + * `windowOpenNoOpener`. + * + * See https://github.com/microsoft/monaco-editor/issues/601 + * See https://github.com/microsoft/monaco-editor/issues/2474 + * See https://mathiasbynens.github.io/rel-noopener/ + */ +export function windowOpenNoOpenerWithSuccess(url: string): boolean { + const newTab = window.open(); if (newTab) { + (newTab as any).opener = null; + newTab.location.href = url; return true; } return false; diff --git a/src/vs/workbench/browser/window.ts b/src/vs/workbench/browser/window.ts index e72a514fc20..d5d3991352d 100644 --- a/src/vs/workbench/browser/window.ts +++ b/src/vs/workbench/browser/window.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { setFullscreen } from 'vs/base/browser/browser'; -import { addDisposableListener, addDisposableThrottledListener, detectFullscreen, EventHelper, EventType, windowOpenNoOpener } from 'vs/base/browser/dom'; +import { addDisposableListener, addDisposableThrottledListener, detectFullscreen, EventHelper, EventType, windowOpenNoOpenerWithSuccess, windowOpenNoOpener } from 'vs/base/browser/dom'; import { domEvent } from 'vs/base/browser/event'; import { timeout } from 'vs/base/common/async'; import { Event } from 'vs/base/common/event'; @@ -144,7 +144,7 @@ export class BrowserWindow extends Disposable { this.openerService.setDefaultExternalOpener({ openExternal: async (href: string) => { if (matchesScheme(href, Schemas.http) || matchesScheme(href, Schemas.https)) { - const opened = windowOpenNoOpener(href); + const opened = windowOpenNoOpenerWithSuccess(href); if (!opened) { const showResult = await this.dialogService.show(Severity.Warning, localize('unableToOpenExternal', "The browser interrupted the opening of a new tab or window. Press 'Open' to open it anyway."), [localize('open', "Open"), localize('learnMore', "Learn More"), localize('cancel', "Cancel")], { cancelId: 2, detail: href }); From 95dee5b5baaf53e5bf31bd4213eda71a40982960 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 12 May 2021 14:59:13 +0200 Subject: [PATCH 36/76] Fixes microsoft/monaco-editor#2345: Add support for browsers that cannot parse regular expressions used for the SnakeCaseAction --- .../linesOperations/linesOperations.ts | 49 +++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/contrib/linesOperations/linesOperations.ts b/src/vs/editor/contrib/linesOperations/linesOperations.ts index 64b689a5fc2..99abacb0715 100644 --- a/src/vs/editor/contrib/linesOperations/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/linesOperations.ts @@ -1045,7 +1045,41 @@ export class TitleCaseAction extends AbstractCaseAction { } } +class BackwardsCompatibleRegExp { + + private _actual: RegExp | null; + private _evaluated: boolean; + + constructor( + private readonly _pattern: string, + private readonly _flags: string + ) { + this._actual = null; + this._evaluated = false; + } + + public get(): RegExp | null { + if (!this._evaluated) { + this._evaluated = true; + try { + this._actual = new RegExp(this._pattern, this._flags); + } catch (err) { + // this browser does not support this regular expression + } + } + return this._actual; + } + + public isSupported(): boolean { + return (this.get() !== null); + } +} + export class SnakeCaseAction extends AbstractCaseAction { + + public static regExp1 = new BackwardsCompatibleRegExp('(\\p{Ll})(\\p{Lu})', 'gmu'); + public static regExp2 = new BackwardsCompatibleRegExp('(\\p{Lu}|\\p{N})(\\p{Lu})(\\p{Ll})', 'gmu'); + constructor() { super({ id: 'editor.action.transformToSnakecase', @@ -1056,9 +1090,15 @@ export class SnakeCaseAction extends AbstractCaseAction { } protected _modifyText(text: string, wordSeparators: string): string { + const regExp1 = SnakeCaseAction.regExp1.get(); + const regExp2 = SnakeCaseAction.regExp2.get(); + if (!regExp1 || !regExp2) { + // cannot support this + return text; + } return (text - .replace(/(\p{Ll})(\p{Lu})/gmu, '$1_$2') - .replace(/(\p{Lu}|\p{N})(\p{Lu})(\p{Ll})/gmu, '$1_$2$3') + .replace(regExp1, '$1_$2') + .replace(regExp2, '$1_$2$3') .toLocaleLowerCase() ); } @@ -1084,4 +1124,7 @@ registerEditorAction(TransposeAction); registerEditorAction(UpperCaseAction); registerEditorAction(LowerCaseAction); registerEditorAction(TitleCaseAction); -registerEditorAction(SnakeCaseAction); + +if (SnakeCaseAction.regExp1.isSupported() && SnakeCaseAction.regExp2.isSupported()) { + registerEditorAction(SnakeCaseAction); +} From 2abf8d37792c333b8d125d6035eb7524ac0d001c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 12 May 2021 15:55:52 +0200 Subject: [PATCH 37/76] Introduce `addMatchMediaChangeListener` with support for Safari 13.x --- src/vs/base/browser/dom.ts | 10 ++++++++++ .../browser/standaloneThemeServiceImpl.ts | 10 ++-------- .../browser/browserHostColorSchemeService.ts | 17 ++++++----------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 90f56d92e05..d95ec0d8c4e 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -1600,3 +1600,13 @@ export function getCookieValue(name: string): string | undefined { return match ? match.pop() : undefined; } + +export function addMatchMediaChangeListener(query: string, callback: () => void): void { + const mediaQueryList = window.matchMedia(query); + if (typeof mediaQueryList.addEventListener === 'function') { + mediaQueryList.addEventListener('change', callback); + } else { + // Safari 13.x + mediaQueryList.addListener(callback); + } +} diff --git a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts index a9abc5fdf15..ece509fa0d0 100644 --- a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts +++ b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts @@ -233,15 +233,9 @@ export class StandaloneThemeServiceImpl extends Disposable implements IStandalon this._updateCSS(); }); - const matchForcedColors = window.matchMedia('(forced-colors: active)'); - const matchForcedColorsListener = () => { + dom.addMatchMediaChangeListener('(forced-colors: active)', () => { this._updateActualTheme(); - }; - if (typeof matchForcedColors.addEventListener === 'function') { - matchForcedColors.addEventListener('change', matchForcedColorsListener); - } else { - matchForcedColors.addListener(matchForcedColorsListener); - } + }); } public registerEditorContainer(domNode: HTMLElement): IDisposable { diff --git a/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts b/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts index 37636a771ed..7d2fb3dde5c 100644 --- a/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts +++ b/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter, Event } from 'vs/base/common/event'; +import * as dom from 'vs/base/browser/dom'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { Disposable } from 'vs/base/common/lifecycle'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -25,18 +26,12 @@ export class BrowserHostColorSchemeService extends Disposable implements IHostCo private registerListeners(): void { - const matchPrefersColorSchemeDark = window.matchMedia('(prefers-color-scheme: dark)'); - const matchForcedColors = window.matchMedia('(forced-colors: active)'); - const listener = () => { + dom.addMatchMediaChangeListener('(prefers-color-scheme: dark)', () => { this._onDidSchemeChangeEvent.fire(); - }; - if (typeof matchForcedColors.addEventListener === 'function') { - matchPrefersColorSchemeDark.addEventListener('change', listener); - matchForcedColors.addEventListener('change', listener); - } else { - matchPrefersColorSchemeDark.addListener(listener); - matchForcedColors.addListener(listener); - } + }); + dom.addMatchMediaChangeListener('(forced-colors: active)', () => { + this._onDidSchemeChangeEvent.fire(); + }); } get onDidChangeColorScheme(): Event { From 39ee13c839bb8cd0825f06f0bce52d8eceb4fd2a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 12 May 2021 16:11:19 +0200 Subject: [PATCH 38/76] Add JSError renderer, experiment with NotebookCellOutputItem#error-factory function, https://github.com/microsoft/vscode/issues/120063 --- src/vs/vscode.proposed.d.ts | 8 +++ src/vs/workbench/api/common/extHostTypes.ts | 7 +++ .../view/output/transforms/richTransform.ts | 60 +++++++++++++++++++ .../contrib/notebook/common/notebookCommon.ts | 1 + 4 files changed, 76 insertions(+) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 51ec435218e..917c26610c3 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1271,9 +1271,17 @@ declare module 'vscode' { // static textplain(value:string): NotebookCellOutputItem; // static errortrace(value:any): NotebookCellOutputItem; + /** + * Creates `application/x.notebook.error` + * + * @param err An error for which an output item is wanted + */ + static error(err: Error): NotebookCellOutputItem; + mime: string; //todo@API string or Unit8Array? + // value: string | Uint8Array | unknown; value: unknown; metadata?: { [key: string]: any }; diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 9f997082238..0cd309dbf10 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -3087,6 +3087,13 @@ export class NotebookCellOutputItem { return typeof (obj).mime === 'string'; } + static error(err: Error): NotebookCellOutputItem { + return new NotebookCellOutputItem( + 'application/x.notebook.error', + JSON.stringify({ name: err.name, message: err.message, stack: err.stack }) + ); + } + constructor( public mime: string, public value: unknown, // JSON'able diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts index dcd4c1d0f7e..60a32f043c7 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts @@ -14,6 +14,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { ILogService } from 'vs/platform/log/common/log'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { handleANSIOutput } from 'vs/workbench/contrib/debug/browser/debugANSIHandling'; @@ -277,6 +278,64 @@ class ErrorRendererContrib extends Disposable implements IOutputRendererContribu } } +class JSErrorRendererContrib implements IOutputRendererContribution { + + constructor( + public notebookEditor: ICommonNotebookEditor, + @IThemeService private readonly _themeService: IThemeService, + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @ILogService private readonly _logService: ILogService, + ) { } + + dispose(): void { + // nothing + } + + getType() { + return RenderOutputType.Mainframe; + } + + getMimetypes() { + return ['application/x.notebook.error']; + } + + render(_output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, _notebookUri: URI): IRenderOutput { + const linkDetector = this._instantiationService.createInstance(LinkDetector); + + for (let item of items) { + + if (typeof item.value !== 'string') { + this._logService.warn('INVALID output item (not a string)', item.value); + continue; + } + + let err: Error; + try { + err = JSON.parse(item.value); + } catch (e) { + this._logService.warn('INVALID output item (failed to parse)', e); + continue; + } + + const header = document.createElement('div'); + const headerMessage = err.name && err.message ? `${err.name}: ${err.message}` : err.name || err.message; + if (headerMessage) { + header.innerText = headerMessage; + container.appendChild(header); + } + const stack = document.createElement('pre'); + stack.classList.add('traceback'); + if (err.stack) { + stack.appendChild(handleANSIOutput(err.stack, linkDetector, this._themeService, undefined)); + } + container.appendChild(stack); + container.classList.add('error'); + } + + return { type: RenderOutputType.Mainframe }; + } +} + class PlainTextRendererContrib extends Disposable implements IOutputRendererContribution { getType() { return RenderOutputType.Mainframe; @@ -459,6 +518,7 @@ NotebookRegistry.registerOutputTransform('jpeg', JPEGRendererContrib); NotebookRegistry.registerOutputTransform('plain', PlainTextRendererContrib); NotebookRegistry.registerOutputTransform('code', CodeRendererContrib); NotebookRegistry.registerOutputTransform('error-trace', ErrorRendererContrib); +NotebookRegistry.registerOutputTransform('jserror', JSErrorRendererContrib); NotebookRegistry.registerOutputTransform('stream-text', StreamRendererContrib); NotebookRegistry.registerOutputTransform('stderr', StderrRendererContrib); diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index a8b2fcaf6f1..98e6211c2e3 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -551,6 +551,7 @@ const _mimeTypeInfo = new Map([ ['image/jpeg', { supportedByCore: true }], ['text/x-javascript', { alwaysSecure: true, supportedByCore: true }], // secure because rendered as text, not executed ['application/x.notebook.error-traceback', { alwaysSecure: true, supportedByCore: true }], + ['application/x.notebook.error', { alwaysSecure: true, supportedByCore: true }], ['application/x.notebook.stream', { alwaysSecure: true, supportedByCore: true, mergeable: true }], ['application/x.notebook.stdout', { alwaysSecure: true, supportedByCore: true, mergeable: true }], ['application/x.notebook.stderr', { alwaysSecure: true, supportedByCore: true, mergeable: true }], From 20d4467d9971dbfabb6bd780da1e6ed8505bd42a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 12 May 2021 16:24:08 +0200 Subject: [PATCH 39/76] Better handling of escaped @ in monarch (microsoft/monaco-editor#2424) --- .../common/monarch/monarchCompile.ts | 13 +++++---- .../standalone/test/monarch/monarch.test.ts | 27 +++++++++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/vs/editor/standalone/common/monarch/monarchCompile.ts b/src/vs/editor/standalone/common/monarch/monarchCompile.ts index 1357baefea7..04dc7241beb 100644 --- a/src/vs/editor/standalone/common/monarch/monarchCompile.ts +++ b/src/vs/editor/standalone/common/monarch/monarchCompile.ts @@ -86,15 +86,14 @@ function createKeywordMatcher(arr: string[], caseInsensitive: boolean = false): * @example /@@text/ will not be replaced and will become /@text/. */ function compileRegExp(lexer: monarchCommon.ILexerMin, str: string): RegExp { + // @@ must be interpreted as a literal @, so we replace all occurences of @@ with a placeholder character + str = str.replace(/@@/g, `\x01`); + let n = 0; let hadExpansion: boolean; do { hadExpansion = false; - str = str.replace(/(.|^)@(\w+)/g, function (s, charBeforeAtSign, attr?) { - if (charBeforeAtSign === '@') { - // do not expand @@ - return s; - } + str = str.replace(/@(\w+)/g, function (s, attr?) { hadExpansion = true; let sub = ''; if (typeof (lexer[attr]) === 'string') { @@ -108,13 +107,13 @@ function compileRegExp(lexer: monarchCommon.ILexerMin, str: string): RegExp { throw monarchCommon.createError(lexer, 'attribute reference \'' + attr + '\' must be a string, used at: ' + str); } } - return charBeforeAtSign + (monarchCommon.empty(sub) ? '' : '(?:' + sub + ')'); + return (monarchCommon.empty(sub) ? '' : '(?:' + sub + ')'); }); n++; } while (hadExpansion && n < 5); // handle escaped @@ - str = str.replace(/@@/g, '@'); + str = str.replace(/\x01/g, '@'); let flags = (lexer.ignoreCase ? 'i' : '') + (lexer.unicode ? 'u' : ''); return new RegExp(str, flags); diff --git a/src/vs/editor/standalone/test/monarch/monarch.test.ts b/src/vs/editor/standalone/test/monarch/monarch.test.ts index fd57288fdca..95686726d7e 100644 --- a/src/vs/editor/standalone/test/monarch/monarch.test.ts +++ b/src/vs/editor/standalone/test/monarch/monarch.test.ts @@ -264,4 +264,31 @@ suite('Monarch', () => { ]); }); + test('microsoft/monaco-editor#2424: Allow to target @@', () => { + const modeService = new ModeServiceImpl(); + + const tokenizer = createMonarchTokenizer(modeService, 'test', { + ignoreCase: false, + tokenizer: { + root: [ + { + regex: /@@@@/, + action: { token: 'ham' } + }, + ], + }, + }); + + const lines = [ + `@@` + ]; + + const actualTokens = getTokens(tokenizer, lines); + assert.deepStrictEqual(actualTokens, [ + [ + new Token(0, 'ham.test', 'test'), + ] + ]); + }); + }); From 1f76da28f6ae10ea569a1c4b8ae327829149a1f9 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 12 May 2021 16:44:20 +0200 Subject: [PATCH 40/76] Fixes microsoft/monaco-editor#2355 --- src/vs/editor/browser/editorExtensions.ts | 8 +++++--- src/vs/editor/contrib/find/findController.ts | 14 +++----------- .../browser/contrib/find/findController.ts | 5 +++-- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/vs/editor/browser/editorExtensions.ts b/src/vs/editor/browser/editorExtensions.ts index 4c22dbf8e3b..9cf6d8db06e 100644 --- a/src/vs/editor/browser/editorExtensions.ts +++ b/src/vs/editor/browser/editorExtensions.ts @@ -349,14 +349,16 @@ export abstract class EditorAction extends EditorCommand { public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise; } +export type EditorActionImplementation = (accessor: ServicesAccessor, editor: ICodeEditor, args: any) => boolean | Promise; + export class MultiEditorAction extends EditorAction { - private readonly _implementations: [number, CommandImplementation][] = []; + private readonly _implementations: [number, EditorActionImplementation][] = []; /** * A higher priority gets to be looked at first */ - public addImplementation(priority: number, implementation: CommandImplementation): IDisposable { + public addImplementation(priority: number, implementation: EditorActionImplementation): IDisposable { this._implementations.push([priority, implementation]); this._implementations.sort((a, b) => b[0] - a[0]); return { @@ -373,7 +375,7 @@ export class MultiEditorAction extends EditorAction { public run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise { for (const impl of this._implementations) { - const result = impl[1](accessor, args); + const result = impl[1](accessor, editor, args); if (result) { if (typeof result === 'boolean') { return; diff --git a/src/vs/editor/contrib/find/findController.ts b/src/vs/editor/contrib/find/findController.ts index 3993c6c6224..b7f3bba4aef 100644 --- a/src/vs/editor/contrib/find/findController.ts +++ b/src/vs/editor/contrib/find/findController.ts @@ -26,7 +26,6 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag import { IThemeService } from 'vs/platform/theme/common/themeService'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; -import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; const SEARCH_STRING_MAX_LENGTH = 524288; @@ -502,12 +501,7 @@ export const StartFindAction = registerMultiEditorAction(new MultiEditorAction({ } })); -StartFindAction.addImplementation(0, (accessor: ServicesAccessor, args: any): boolean | Promise => { - const codeEditorService = accessor.get(ICodeEditorService); - const editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor(); - if (!editor) { - return false; - } +StartFindAction.addImplementation(0, (accessor: ServicesAccessor, editor: ICodeEditor, args: any): boolean | Promise => { const controller = CommonFindController.get(editor); if (!controller) { return false; @@ -726,10 +720,8 @@ export const StartFindReplaceAction = registerMultiEditorAction(new MultiEditorA } })); -StartFindReplaceAction.addImplementation(0, (accessor: ServicesAccessor, args: any): boolean | Promise => { - const codeEditorService = accessor.get(ICodeEditorService); - const editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor(); - if (!editor || !editor.hasModel() || editor.getOption(EditorOption.readOnly)) { +StartFindReplaceAction.addImplementation(0, (accessor: ServicesAccessor, editor: ICodeEditor, args: any): boolean | Promise => { + if (!editor.hasModel() || editor.getOption(EditorOption.readOnly)) { return false; } const controller = CommonFindController.get(editor); diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts index 007a73f8dde..29364b4abc7 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts @@ -28,6 +28,7 @@ import { StartFindAction, StartFindReplaceAction } from 'vs/editor/contrib/find/ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { NLS_MATCHES_LOCATION, NLS_NO_RESULTS } from 'vs/editor/contrib/find/findWidget'; import { FindModel } from 'vs/workbench/contrib/notebook/browser/contrib/find/findModel'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; const FIND_HIDE_TRANSITION = 'find-hide-transition'; const FIND_SHOW_TRANSITION = 'find-show-transition'; @@ -325,7 +326,7 @@ registerAction2(class extends Action2 { } }); -StartFindAction.addImplementation(100, (accessor: ServicesAccessor, args: any) => { +StartFindAction.addImplementation(100, (accessor: ServicesAccessor, codeEditor: ICodeEditor, args: any) => { const editorService = accessor.get(IEditorService); const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); @@ -338,7 +339,7 @@ StartFindAction.addImplementation(100, (accessor: ServicesAccessor, args: any) = return true; }); -StartFindReplaceAction.addImplementation(100, (accessor: ServicesAccessor, args: any) => { +StartFindReplaceAction.addImplementation(100, (accessor: ServicesAccessor, codeEditor: ICodeEditor, args: any) => { const editorService = accessor.get(IEditorService); const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); From a53919b8e925b9c42af49c711db1d57df119c481 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 12 May 2021 16:57:19 +0200 Subject: [PATCH 41/76] Fixes microsoft/monaco-editor#2466 --- src/vs/editor/browser/widget/codeEditorWidget.ts | 6 +++++- .../standalone/browser/standaloneCodeEditor.ts | 15 +++++++++++++++ .../browser/standaloneCodeServiceImpl.ts | 8 +++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index cbf16da575e..1365a731be3 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -226,7 +226,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE protected readonly _instantiationService: IInstantiationService; protected readonly _contextKeyService: IContextKeyService; private readonly _notificationService: INotificationService; - private readonly _codeEditorService: ICodeEditorService; + protected readonly _codeEditorService: ICodeEditorService; private readonly _commandService: ICommandService; private readonly _themeService: IThemeService; @@ -1048,6 +1048,10 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE return; } + this._triggerCommand(handlerId, payload); + } + + protected _triggerCommand(handlerId: string, payload: any): void { this._commandService.executeCommand(handlerId, payload); } diff --git a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts index 89dff41d626..77884d5ffde 100644 --- a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts @@ -34,6 +34,7 @@ import { StandaloneThemeServiceImpl } from 'vs/editor/standalone/browser/standal import { IModelService } from 'vs/editor/common/services/modelService'; import { ILanguageSelection, IModeService } from 'vs/editor/common/services/modeService'; import { URI } from 'vs/base/common/uri'; +import { StandaloneCodeEditorServiceImpl } from 'vs/editor/standalone/browser/standaloneCodeServiceImpl'; /** * Description of an action contribution @@ -363,6 +364,20 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon return toDispose; } + + protected override _triggerCommand(handlerId: string, payload: any): void { + if (this._codeEditorService instanceof StandaloneCodeEditorServiceImpl) { + // Help commands find this editor as the active editor + try { + this._codeEditorService.setActiveCodeEditor(this); + super._triggerCommand(handlerId, payload); + } finally { + this._codeEditorService.setActiveCodeEditor(null); + } + } else { + super._triggerCommand(handlerId, payload); + } + } } export class StandaloneEditor extends StandaloneCodeEditor implements IStandaloneCodeEditor { diff --git a/src/vs/editor/standalone/browser/standaloneCodeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneCodeServiceImpl.ts index f7808cfa6fc..e14ce169335 100644 --- a/src/vs/editor/standalone/browser/standaloneCodeServiceImpl.ts +++ b/src/vs/editor/standalone/browser/standaloneCodeServiceImpl.ts @@ -18,6 +18,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; export class StandaloneCodeEditorServiceImpl extends CodeEditorServiceImpl { private readonly _editorIsOpen: IContextKey; + private _activeCodeEditor: ICodeEditor | null; constructor( styleSheet: GlobalStyleSheet | null, @@ -28,6 +29,7 @@ export class StandaloneCodeEditorServiceImpl extends CodeEditorServiceImpl { this.onCodeEditorAdd(() => this._checkContextKey()); this.onCodeEditorRemove(() => this._checkContextKey()); this._editorIsOpen = contextKeyService.createKey('editorIsOpen', false); + this._activeCodeEditor = null; } private _checkContextKey(): void { @@ -41,8 +43,12 @@ export class StandaloneCodeEditorServiceImpl extends CodeEditorServiceImpl { this._editorIsOpen.set(hasCodeEditor); } + public setActiveCodeEditor(activeCodeEditor: ICodeEditor | null): void { + this._activeCodeEditor = activeCodeEditor; + } + public getActiveCodeEditor(): ICodeEditor | null { - return null; // not supported in the standalone case + return this._activeCodeEditor; } public openCodeEditor(input: IResourceEditorInput, source: ICodeEditor | null, sideBySide?: boolean): Promise { From dbc2166e56bdfadc2d3161795aa28e704ff5b054 Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Wed, 12 May 2021 11:20:04 -0400 Subject: [PATCH 42/76] Fix #123360 --- src/vs/workbench/browser/parts/editor/editorCommands.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index f155c7aa228..34f61e1ec8a 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -487,7 +487,7 @@ function registerOpenEditorAPICommands(): void { group = editorGroupsService.getGroup(viewColumnToEditorGroup(editorGroupsService, columnArg)) ?? editorGroupsService.activeGroup; } - return editorService.openEditor({ resource: URI.revive(resource), options: { ...optionsArg, override: id } }, group); + return editorService.openEditor({ resource: URI.revive(resource), options: { ...optionsArg, pinned: true, override: id } }, group); }); } From 22fc27d4cf7bb44d4d846642f98e32f098538f4b Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Wed, 12 May 2021 11:38:26 -0400 Subject: [PATCH 43/76] Closes #123674 --- .../services/editor/browser/editorOverrideService.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/vs/workbench/services/editor/browser/editorOverrideService.ts b/src/vs/workbench/services/editor/browser/editorOverrideService.ts index df34f24d283..bcb8ad48584 100644 --- a/src/vs/workbench/services/editor/browser/editorOverrideService.ts +++ b/src/vs/workbench/services/editor/browser/editorOverrideService.ts @@ -130,9 +130,7 @@ export class EditorOverrideService extends Disposable implements IEditorOverride const input = await this.doOverrideEditorInput(editor, options, group, selectedContribution); if (conflictingDefault && input) { // Wait one second to give the user ample time to see the current editor then ask them to configure a default - setTimeout(() => { - this.doHandleConflictingDefaults(selectedContribution.editorInfo.label, input.editor, input.options ?? options, group); - }, 1200); + this.doHandleConflictingDefaults(selectedContribution.editorInfo.label, input.editor, input.options ?? options, group); } // Dispose of the passed in editor as we will return a new one if (!input?.editor.matches(editor)) { From d1b73271581dba95401667e80240a00fb1fb982f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 12 May 2021 19:16:13 +0200 Subject: [PATCH 44/76] kernel action view item shows icon _and_ label --- .../media/notebookKernelActionViewItem.css | 24 +++++++++++++++++++ .../browser/notebookKernelActionViewItem.ts | 22 ++++++++++++++--- 2 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/vs/workbench/contrib/notebook/browser/media/notebookKernelActionViewItem.css diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebookKernelActionViewItem.css b/src/vs/workbench/contrib/notebook/browser/media/notebookKernelActionViewItem.css new file mode 100644 index 00000000000..5f394da2d1f --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/media/notebookKernelActionViewItem.css @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +.monaco-workbench .kernel-action-view-item { + border-radius: 5px; +} +.monaco-workbench .kernel-action-view-item:hover { + background-color: var(--code-toolbarHoverBackground); +} + +.monaco-workbench .kernel-action-view-item .action-label { + display: inline-flex; +} + +.monaco-workbench .kernel-action-view-item .kernel-label { + font-size: 11px; + padding: 3px 5px 3px 3px; + border-radius: 5px; + height: 16px; + display: inline-flex; + vertical-align: text-bottom; +} diff --git a/src/vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem.ts b/src/vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem.ts index 11345051abc..ab718676eac 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem.ts @@ -3,11 +3,22 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import 'vs/css!./media/notebookKernelActionViewItem'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { Action, IAction } from 'vs/base/common/actions'; import { localize } from 'vs/nls'; +import { registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEditor'; +import { selectKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { INotebookKernelMatchResult, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { toolbarHoverBackground } from 'vs/platform/theme/common/colorRegistry'; + +registerThemingParticipant((theme, collector) => { + const value = theme.getColor(toolbarHoverBackground); + collector.addRule(`:root { + --code-toolbarHoverBackground: ${value}; + }`); +}); export class NotebooKernelActionViewItem extends ActionViewItem { @@ -18,8 +29,8 @@ export class NotebooKernelActionViewItem extends ActionViewItem { ) { super( undefined, - new Action('fakeAction', undefined, undefined, true, (event) => actualAction.run(event)), - { label: true, icon: false } + new Action('fakeAction', undefined, ThemeIcon.asClassName(selectKernelIcon), true, (event) => actualAction.run(event)), + { label: false, icon: true } ); this._register(_editor.onDidChangeModel(this._update, this)); } @@ -27,7 +38,12 @@ export class NotebooKernelActionViewItem extends ActionViewItem { override render(container: HTMLElement): void { this._update(); super.render(container); - this.label!.style.display = 'inline-block'; + container.classList.add('kernel-action-view-item'); + const label = document.createElement('a'); + label.classList.add('kernel-label'); + label.innerText = this._action.label; + label.title = this._action.tooltip; + container.appendChild(label); } private _update(): void { From 2f282bbefb2e107f35344580b99334a6b99ec467 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 12 May 2021 19:28:19 +0200 Subject: [PATCH 45/76] Log which extension creates what controller when, https://github.com/microsoft/vscode/issues/122409#issuecomment-833448914 --- src/vs/workbench/api/common/extHost.api.impl.ts | 2 +- src/vs/workbench/api/common/extHostNotebookKernels.ts | 8 +++++++- .../test/browser/api/extHostNotebookKernel2.test.ts | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 49ff0bdce96..0c5b1b5aca2 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -145,7 +145,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors, extHostLogService)); const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostLogService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadBulkEdits))); const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, extHostDocuments, extHostLogService, extensionStoragePaths)); - const extHostNotebookKernels = rpcProtocol.set(ExtHostContext.ExtHostNotebookKernels, new ExtHostNotebookKernels(rpcProtocol, initData, extHostNotebook)); + const extHostNotebookKernels = rpcProtocol.set(ExtHostContext.ExtHostNotebookKernels, new ExtHostNotebookKernels(rpcProtocol, initData, extHostNotebook, extHostLogService)); const extHostEditors = rpcProtocol.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(rpcProtocol, extHostDocumentsAndEditors)); const extHostTreeViews = rpcProtocol.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(rpcProtocol.getProxy(MainContext.MainThreadTreeViews), extHostCommands, extHostLogService)); const extHostEditorInsets = rpcProtocol.set(ExtHostContext.ExtHostEditorInsets, new ExtHostEditorInsets(rpcProtocol.getProxy(MainContext.MainThreadEditorInsets), extHostEditors, { ...initData.environment, remote: initData.remote })); diff --git a/src/vs/workbench/api/common/extHostNotebookKernels.ts b/src/vs/workbench/api/common/extHostNotebookKernels.ts index 3f91dd9e8f9..3e7373d7e1b 100644 --- a/src/vs/workbench/api/common/extHostNotebookKernels.ts +++ b/src/vs/workbench/api/common/extHostNotebookKernels.ts @@ -20,6 +20,7 @@ import { CellEditType, IImmediateCellEditOperation, NullablePartialNotebookCellM import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { NotebookCellExecutionState } from 'vs/workbench/api/common/extHostTypes'; import { asArray } from 'vs/base/common/arrays'; +import { ILogService } from 'vs/platform/log/common/log'; interface IKernelData { extensionId: ExtensionIdentifier, @@ -40,7 +41,8 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { constructor( private readonly _mainContext: IMainContext, private readonly _initData: IExtHostInitDataService, - private readonly _extHostNotebook: ExtHostNotebookController + private readonly _extHostNotebook: ExtHostNotebookController, + @ILogService private readonly _logService: ILogService, ) { this._proxy = _mainContext.getProxy(MainContext.MainThreadNotebookKernels); } @@ -53,9 +55,12 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { } } + const handle = this._handlePool++; const that = this; + this._logService.trace(`NotebookController[${handle}], CREATED by ${extension.identifier.value}, ${id}`); + const _defaultExecutHandler = () => console.warn(`NO execute handler from notebook controller '${data.id}' of extension: '${extension.identifier}'`); let isDisposed = false; @@ -170,6 +175,7 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { }, dispose: () => { if (!isDisposed) { + this._logService.trace(`NotebookController[${handle}], DISPOSED`); isDisposed = true; this._kernelData.delete(handle); commandDisposables.dispose(); diff --git a/src/vs/workbench/test/browser/api/extHostNotebookKernel2.test.ts b/src/vs/workbench/test/browser/api/extHostNotebookKernel2.test.ts index adf67d28a42..5bfdd1356c3 100644 --- a/src/vs/workbench/test/browser/api/extHostNotebookKernel2.test.ts +++ b/src/vs/workbench/test/browser/api/extHostNotebookKernel2.test.ts @@ -114,7 +114,8 @@ suite('NotebookKernel', function () { extHostNotebookKernels = new ExtHostNotebookKernels( rpcProtocol, new class extends mock() { }, - extHostNotebooks + extHostNotebooks, + new NullLogService() ); }); From c6beaef489daca62fdf1fadd1c9b942df40ca0f4 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 12 May 2021 19:46:11 +0200 Subject: [PATCH 46/76] added logging for https://github.com/microsoft/vscode/issues/123700 --- src/vs/workbench/api/common/extHostNotebookKernels.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/api/common/extHostNotebookKernels.ts b/src/vs/workbench/api/common/extHostNotebookKernels.ts index 3e7373d7e1b..5bff02dac35 100644 --- a/src/vs/workbench/api/common/extHostNotebookKernels.ts +++ b/src/vs/workbench/api/common/extHostNotebookKernels.ts @@ -169,6 +169,7 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { throw new Error('notebook controller is DISPOSED'); } if (!associatedNotebooks.has(cell.notebook.uri)) { + that._logService.trace(`NotebookController[${handle}] NOT associated to notebook, associated to THESE notebooks:`, Array.from(associatedNotebooks.keys()).map(u => u.toString())); throw new Error(`notebook controller is NOT associated to notebook: ${cell.notebook.uri.toString()}`); } return that._createNotebookCellExecution(cell); @@ -218,6 +219,7 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { } else { obj.associatedNotebooks.delete(notebook.uri); } + this._logService.trace(`NotebookController[${handle}]`, notebook.uri.toString(), value); // send event obj.onDidChangeSelection.fire({ selected: value, From dd924d774ff66846ce9911286a06f36faee711a1 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 12 May 2021 11:01:41 -0700 Subject: [PATCH 47/76] Remove leftover trusted metadata references --- .../notebook/browser/view/renderers/cellOutput.ts | 15 ++------------- .../browser/viewModel/notebookViewModel.ts | 4 ---- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts index 8b5c7447bca..421cbba176b 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts @@ -13,7 +13,7 @@ import { IQuickPickItem, IQuickInputService } from 'vs/platform/quickinput/commo import { CodeCellRenderTemplate, ICellOutputViewModel, IInsetRenderOutput, INotebookEditor, IRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; -import { BUILTIN_RENDERER_ID, CellUri, NotebookCellOutputsSplice, IOrderedMimeType, mimeTypeIsAlwaysSecure, INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { BUILTIN_RENDERER_ID, CellUri, NotebookCellOutputsSplice, IOrderedMimeType, INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IMarkdownString } from 'vs/base/common/htmlContent'; import { renderMarkdown } from 'vs/base/browser/markdownRenderer'; @@ -444,18 +444,7 @@ export class CellOutputContainer extends Disposable { } private _calcuateOutputsToRender(): ICellOutputViewModel[] { - const outputs = this.viewCell.outputsViewModels.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputsViewModels.length)); - if (!this.notebookEditor.viewModel!.metadata.trusted) { - // not trusted - const secureOutput = outputs.filter(output => { - const mimeTypes = output.model.outputs.map(op => op.mime); - return mimeTypes.some(mimeTypeIsAlwaysSecure); - }); - - return secureOutput; - } - - return outputs; + return this.viewCell.outputsViewModels.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputsViewModels.length)); } private _outputHeightTimer: any = null; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 4184eb5247b..840b8621878 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -173,10 +173,6 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD return this._notebook.metadata; } - get trusted() { - return !!this._notebook.metadata?.trusted; - } - private readonly _onDidChangeViewCells = this._register(new Emitter()); get onDidChangeViewCells(): Event { return this._onDidChangeViewCells.event; } From 2f2ca2ea1922809e7404d84808d8ff83cc00bb53 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 12 May 2021 20:02:37 +0200 Subject: [PATCH 48/76] more trace logging, https://github.com/microsoft/vscode/issues/123700 --- src/vs/workbench/api/common/extHostNotebookKernels.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/api/common/extHostNotebookKernels.ts b/src/vs/workbench/api/common/extHostNotebookKernels.ts index 5bff02dac35..91007850945 100644 --- a/src/vs/workbench/api/common/extHostNotebookKernels.ts +++ b/src/vs/workbench/api/common/extHostNotebookKernels.ts @@ -219,7 +219,7 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { } else { obj.associatedNotebooks.delete(notebook.uri); } - this._logService.trace(`NotebookController[${handle}]`, notebook.uri.toString(), value); + this._logService.trace(`NotebookController[${handle}] ASSOCIATE notebook`, notebook.uri.toString(), value); // send event obj.onDidChangeSelection.fire({ selected: value, @@ -244,9 +244,11 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { } try { + this._logService.trace(`NotebookController[${handle}] EXECUTE cells`, document.uri.toString(), cells.length); await obj.controller.executeHandler.call(obj.controller, cells, document.apiNotebook, obj.controller); } catch (err) { // + this._logService.error(`NotebookController[${handle}] execute cells FAILED`, err); console.error(err); } } From a2f7ad10ca549ddcc10f72d61220719794a35636 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 12 May 2021 12:39:05 -0700 Subject: [PATCH 49/76] Try better fix for loading mixed local/remote notebook resources (#123638) This is a follow up on 19cda32aafccb88db45622e7ae9be90cb71c9744. It removes the `useRootAuthority` workaround we introduced to instead take the authority that is passed in as part of the resource uri --- .../browser/view/renderers/backLayerWebView.ts | 18 +++++++++--------- .../webview/browser/baseWebviewElement.ts | 2 -- .../contrib/webview/browser/resourceLoading.ts | 12 +++++------- .../contrib/webview/browser/webview.ts | 1 - 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index b8a0d789cca..37761fdc528 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -727,13 +727,13 @@ export class BackLayerWebView extends Disposable { if (!subRenderers.has(renderer.dependsOn)) { subRenderers.set(renderer.dependsOn, []); } - const entryPoint = this.asWebviewUri(renderer.entrypoint); + const entryPoint = this.asWebviewUri(renderer.entrypoint, renderer.extensionLocation); subRenderers.get(renderer.dependsOn)!.push({ entrypoint: entryPoint.toString(true) }); } } return topLevelMarkdownRenderers.map((renderer): WebviewPreloadRenderer => { - const src = this.asWebviewUri(renderer.entrypoint); + const src = this.asWebviewUri(renderer.entrypoint, renderer.extensionLocation); return { entrypoint: src.toString(), mimeTypes: [markdownMimeType], @@ -742,12 +742,13 @@ export class BackLayerWebView extends Disposable { }); } - private asWebviewUri(uri: URI) { + private asWebviewUri(uri: URI, fromExtension: URI | undefined) { + const remoteAuthority = fromExtension?.scheme === Schemas.vscodeRemote ? fromExtension.authority : undefined; return asWebviewUri({ isExtensionDevelopmentDebug: this.environmentService.isExtensionDevelopment, webviewCspSource: this.environmentService.webviewCspSource, webviewResourceRoot: this.environmentService.webviewResourceRoot, - remote: { authority: undefined } // TODO + remote: { authority: remoteAuthority } }, this.id, uri); } @@ -781,11 +782,11 @@ export class BackLayerWebView extends Disposable { resolveFunc = resolve; }); - const baseUrl = this.asWebviewUri(dirname(this.documentUri)); + const baseUrl = this.asWebviewUri(dirname(this.documentUri), undefined); if (!isWeb) { const loaderUri = FileAccess.asFileUri('vs/loader.js', require); - const loader = this.asWebviewUri(loaderUri); + const loader = this.asWebviewUri(loaderUri, undefined); coreDependencies = `