Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vscode.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/vs/workbench/contrib/notebook')
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.css7
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts78
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts4
-rw-r--r--src/vs/workbench/contrib/notebook/browser/controller/editActions.ts37
-rw-r--r--src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts52
-rw-r--r--src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts2
-rw-r--r--src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts16
-rw-r--r--src/vs/workbench/contrib/notebook/browser/media/notebookToolbar.css4
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts1
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebookEditor.ts33
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts19
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebookExecutionStateServiceImpl.ts36
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/cellParts/cellToolbars.ts45
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts16
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts2
-rw-r--r--src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts13
-rw-r--r--src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts1
-rw-r--r--src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts6
-rw-r--r--src/vs/workbench/contrib/notebook/common/notebookExecutionStateService.ts6
-rw-r--r--src/vs/workbench/contrib/notebook/common/notebookPerformance.ts36
-rw-r--r--src/vs/workbench/contrib/notebook/test/browser/testNotebookEditor.ts9
21 files changed, 273 insertions, 150 deletions
diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.css b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.css
index d9701c95197..52cfc8adcac 100644
--- a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.css
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.css
@@ -9,9 +9,9 @@
position: absolute;
top: -45px;
right: 18px;
- width: 318px;
+ width: var(--notebook-find-width);
max-width: calc(100% - 28px - 28px - 8px);
- pointer-events: none;
+ padding:0 var(--notebook-find-horizontal-padding);
transition: top 200ms linear;
visibility: hidden;
}
@@ -158,3 +158,6 @@
.monaco-workbench .simple-fr-replace-part .monaco-inputbox > .ibwrapper > .input {
height: 24px;
}
+.monaco-workbench .simple-fr-find-part-wrapper .monaco-sash {
+ left: 0 !important;
+}
diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts
index 59f060f6421..f2d0a44853c 100644
--- a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts
@@ -18,7 +18,7 @@ import * as nls from 'vs/nls';
import { ContextScopedReplaceInput, registerAndCreateHistoryNavigationContext } from 'vs/platform/history/browser/contextScopedHistoryWidget';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
-import { editorWidgetBackground, editorWidgetForeground, inputActiveOptionBackground, inputActiveOptionBorder, inputActiveOptionForeground, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationWarningForeground, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
+import { editorWidgetBackground, editorWidgetBorder, editorWidgetForeground, editorWidgetResizeBorder, inputActiveOptionBackground, inputActiveOptionBorder, inputActiveOptionForeground, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationWarningForeground, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
import { registerIcon, widgetClose } from 'vs/platform/theme/common/iconRegistry';
import { attachProgressBarStyler } from 'vs/platform/theme/common/styler';
import { IColorTheme, IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService';
@@ -35,6 +35,8 @@ import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { filterIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons';
import { NotebookFindFilters } from 'vs/workbench/contrib/notebook/browser/contrib/find/findFilters';
import { isSafari } from 'vs/base/common/platform';
+import { ISashEvent, Orientation, Sash } from 'vs/base/browser/ui/sash/sash';
+import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
const NLS_FIND_INPUT_LABEL = nls.localize('label.find', "Find");
const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find");
@@ -55,6 +57,8 @@ const NOTEBOOK_FIND_IN_MARKUP_PREVIEW = nls.localize('notebook.find.filter.findI
const NOTEBOOK_FIND_IN_CODE_INPUT = nls.localize('notebook.find.filter.findInCodeInput', "Code Cell Source");
const NOTEBOOK_FIND_IN_CODE_OUTPUT = nls.localize('notebook.find.filter.findInCodeOutput', "Cell Output");
+const NOTEBOOK_FIND_WIDGET_INITIAL_WIDTH = 318;
+const NOTEBOOK_FIND_WIDGET_INITIAL_HORIZONTAL_PADDING = 4;
class NotebookFindFilterActionViewItem extends DropdownMenuActionViewItem {
constructor(readonly filters: NotebookFindFilters, action: IAction, actionRunner: IActionRunner, @IContextMenuService contextMenuService: IContextMenuService) {
super(action,
@@ -256,6 +260,8 @@ export abstract class SimpleFindReplaceWidget extends Widget {
protected _replaceBtn!: SimpleButton;
protected _replaceAllBtn!: SimpleButton;
+ private readonly _resizeSash: Sash;
+ private _resizeOriginalWidth = NOTEBOOK_FIND_WIDGET_INITIAL_WIDTH;
private _isVisible: boolean = false;
private _isReplaceVisible: boolean = false;
@@ -274,7 +280,8 @@ export abstract class SimpleFindReplaceWidget extends Widget {
@IMenuService readonly menuService: IMenuService,
@IContextMenuService readonly contextMenuService: IContextMenuService,
@IInstantiationService readonly instantiationService: IInstantiationService,
- protected readonly _state: FindReplaceState<NotebookFindFilters> = new FindReplaceState<NotebookFindFilters>()
+ protected readonly _state: FindReplaceState<NotebookFindFilters> = new FindReplaceState<NotebookFindFilters>(),
+ protected readonly _notebookEditor: INotebookEditor,
) {
super();
@@ -339,7 +346,8 @@ export abstract class SimpleFindReplaceWidget extends Widget {
this.updateButtons(this.foundMatch);
return { content: e.message };
}
- }
+ },
+ flexibleWidth: true,
}
));
@@ -474,6 +482,58 @@ export abstract class SimpleFindReplaceWidget extends Widget {
this._innerReplaceDomNode.appendChild(this._replaceBtn.domNode);
this._innerReplaceDomNode.appendChild(this._replaceAllBtn.domNode);
+
+ this._resizeSash = this._register(new Sash(this._domNode, { getVerticalSashLeft: () => 0 }, { orientation: Orientation.VERTICAL, size: 2 }));
+
+ this._register(this._resizeSash.onDidStart(() => {
+ this._resizeOriginalWidth = this._getDomWidth();
+ }));
+
+ this._register(this._resizeSash.onDidChange((evt: ISashEvent) => {
+ let width = this._resizeOriginalWidth + evt.startX - evt.currentX;
+ if (width < NOTEBOOK_FIND_WIDGET_INITIAL_WIDTH) {
+ width = NOTEBOOK_FIND_WIDGET_INITIAL_WIDTH;
+ }
+
+ const maxWidth = this._getMaxWidth();
+ if (width > maxWidth) {
+ width = maxWidth;
+ }
+
+ this._domNode.style.width = `${width}px`;
+
+ if (this._isReplaceVisible) {
+ this._replaceInput.width = dom.getTotalWidth(this._findInput.domNode);
+ }
+
+ this._findInput.inputBox.layout();
+ }));
+
+ this._register(this._resizeSash.onDidReset(() => {
+ // users double click on the sash
+ // try to emulate what happens with editor findWidget
+ const currentWidth = this._getDomWidth();
+ let width = NOTEBOOK_FIND_WIDGET_INITIAL_WIDTH;
+
+ if (currentWidth <= NOTEBOOK_FIND_WIDGET_INITIAL_WIDTH) {
+ width = this._getMaxWidth();
+ }
+
+ this._domNode.style.width = `${width}px`;
+ if (this._isReplaceVisible) {
+ this._replaceInput.width = dom.getTotalWidth(this._findInput.domNode);
+ }
+
+ this._findInput.inputBox.layout();
+ }));
+ }
+
+ private _getMaxWidth() {
+ return this._notebookEditor.getLayoutInfo().width - 64;
+ }
+
+ private _getDomWidth() {
+ return dom.getTotalWidth(this._domNode) - (NOTEBOOK_FIND_WIDGET_INITIAL_HORIZONTAL_PADDING * 2);
}
getCellToolbarActions(menu: IMenu): { primary: IAction[]; secondary: IAction[] } {
@@ -727,4 +787,16 @@ registerThemingParticipant((theme, collector) => {
if (inputActiveOptionBackgroundColor) {
collector.addRule(`.simple-fr-find-part .find-filter-button > .monaco-action-bar .action-label.notebook-filters.checked { background-color: ${inputActiveOptionBackgroundColor}; }`);
}
+
+ const resizeBorderBackground = theme.getColor(editorWidgetResizeBorder) ?? theme.getColor(editorWidgetBorder);
+ if (resizeBorderBackground) {
+ collector.addRule(`.monaco-workbench .simple-fr-find-part-wrapper .monaco-sash { background-color: ${resizeBorderBackground}; }`);
+ }
+
+ collector.addRule(`
+ :root {
+ --notebook-find-width: ${NOTEBOOK_FIND_WIDGET_INITIAL_WIDTH}px;
+ --notebook-find-horizontal-padding: ${NOTEBOOK_FIND_WIDGET_INITIAL_HORIZONTAL_PADDING}px;
+ }
+ `);
});
diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts
index c027d8137d4..9c38190c342 100644
--- a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts
@@ -48,7 +48,7 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote
private _findModel: FindModel;
constructor(
- private readonly _notebookEditor: INotebookEditor,
+ _notebookEditor: INotebookEditor,
@IContextViewService contextViewService: IContextViewService,
@IContextKeyService contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService,
@@ -57,7 +57,7 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote
@IMenuService menuService: IMenuService,
@IInstantiationService instantiationService: IInstantiationService,
) {
- super(contextViewService, contextKeyService, themeService, configurationService, menuService, contextMenuService, instantiationService, new FindReplaceState<NotebookFindFilters>());
+ super(contextViewService, contextKeyService, themeService, configurationService, menuService, contextMenuService, instantiationService, new FindReplaceState<NotebookFindFilters>(), _notebookEditor);
this._findModel = new FindModel(this._notebookEditor, this._state, this._configurationService);
DOM.append(this._notebookEditor.getDomNode(), this.getDomNode());
diff --git a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts
index 1f64bddb5e3..06e089a7c6b 100644
--- a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts
+++ b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts
@@ -11,9 +11,8 @@ import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import { IModelService } from 'vs/editor/common/services/model';
import { ILanguageService } from 'vs/editor/common/languages/language';
import { localize } from 'vs/nls';
-import { MenuId, MenuItemAction, registerAction2 } from 'vs/platform/actions/common/actions';
-import { ICommandService } from 'vs/platform/commands/common/commands';
-import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
+import { MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
+import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, InputFocusedContextKey } from 'vs/platform/contextkey/common/contextkeys';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
@@ -35,26 +34,6 @@ const EDIT_CELL_COMMAND_ID = 'notebook.cell.edit';
const DELETE_CELL_COMMAND_ID = 'notebook.cell.delete';
const CLEAR_CELL_OUTPUTS_COMMAND_ID = 'notebook.cell.clearOutputs';
-export class DeleteCellAction extends MenuItemAction {
- constructor(
- @IContextKeyService contextKeyService: IContextKeyService,
- @ICommandService commandService: ICommandService
- ) {
- super(
- {
- id: DELETE_CELL_COMMAND_ID,
- title: localize('notebookActions.deleteCell', "Delete Cell"),
- icon: icons.deleteCellIcon,
- precondition: NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true)
- },
- undefined,
- { shouldForwardArgs: true },
- undefined,
- contextKeyService,
- commandService);
- }
-}
-
registerAction2(class EditCellAction extends NotebookCellAction {
constructor() {
super(
@@ -158,6 +137,18 @@ registerAction2(class DeleteCellAction extends NotebookCellAction {
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_EDITABLE, ContextKeyExpr.not(InputFocusedContextKey)),
weight: KeybindingWeight.WorkbenchContrib
},
+ menu: [
+ {
+ id: MenuId.NotebookCellDelete,
+ when: NOTEBOOK_EDITOR_EDITABLE,
+ group: CELL_TITLE_CELL_GROUP_ID
+ },
+ {
+ id: MenuId.InteractiveCellDelete,
+ when: NOTEBOOK_EDITOR_EDITABLE,
+ group: CELL_TITLE_CELL_GROUP_ID
+ }
+ ],
icon: icons.deleteCellIcon
});
}
diff --git a/src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts
index 3e54598b92b..7b190d89c14 100644
--- a/src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts
+++ b/src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts
@@ -15,7 +15,7 @@ import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { EditorsOrder } from 'vs/workbench/common/editor';
import { insertCell } from 'vs/workbench/contrib/notebook/browser/controller/cellOperations';
import { cellExecutionArgs, CellToolbarOrder, CELL_TITLE_CELL_GROUP_ID, executeNotebookCondition, getContextFromActiveEditor, getContextFromUri, INotebookActionContext, INotebookCellActionContext, INotebookCellToolbarActionContext, INotebookCommandContext, NotebookAction, NotebookCellAction, NotebookMultiCellAction, NOTEBOOK_EDITOR_WIDGET_ACTION_WEIGHT, parseMultiCellExecutionArgs } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
-import { NOTEBOOK_CELL_EXECUTING, NOTEBOOK_CELL_EXECUTION_STATE, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_HAS_RUNNING_CELL, NOTEBOOK_INTERRUPTIBLE_KERNEL, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_KERNEL_SOURCE_COUNT, NOTEBOOK_MISSING_KERNEL_EXTENSION } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
+import { NOTEBOOK_CELL_EXECUTING, NOTEBOOK_CELL_EXECUTION_STATE, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_HAS_RUNNING_CELL, NOTEBOOK_INTERRUPTIBLE_KERNEL, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_KERNEL_SOURCE_COUNT, NOTEBOOK_LAST_CELL_FAILED, NOTEBOOK_MISSING_KERNEL_EXTENSION } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
import { CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons';
import { CellKind, NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
@@ -35,6 +35,7 @@ const EXECUTE_CELL_AND_BELOW = 'notebook.cell.executeCellAndBelow';
const EXECUTE_CELLS_ABOVE = 'notebook.cell.executeCellsAbove';
const RENDER_ALL_MARKDOWN_CELLS = 'notebook.renderAllMarkdownCells';
const REVEAL_RUNNING_CELL = 'notebook.revealRunningCell';
+const REVEAL_LAST_FAILED_CELL = 'notebook.revealLastFailedCell';
// If this changes, update getCodeCellExecutionContextKeyService to match
export const executeCondition = ContextKeyExpr.and(
@@ -594,3 +595,52 @@ registerAction2(class RevealRunningCellAction extends NotebookAction {
}
}
});
+
+registerAction2(class RevealLastFailedCellAction extends NotebookAction {
+ constructor() {
+ super({
+ id: REVEAL_LAST_FAILED_CELL,
+ title: localize('revealLastFailedCell', "Go to Most Recently Failed Cell"),
+ tooltip: localize('revealLastFailedCell', "Go to Most Recently Failed Cell"),
+ shortTitle: localize('revealLastFailedCellShort', "Go To"),
+ precondition: NOTEBOOK_LAST_CELL_FAILED,
+ menu: [
+ {
+ id: MenuId.EditorTitle,
+ when: ContextKeyExpr.and(
+ NOTEBOOK_IS_ACTIVE_EDITOR,
+ NOTEBOOK_LAST_CELL_FAILED,
+ NOTEBOOK_HAS_RUNNING_CELL.toNegated(),
+ ContextKeyExpr.notEquals('config.notebook.globalToolbar', true)
+ ),
+ group: 'navigation',
+ order: 0
+ },
+ {
+ id: MenuId.NotebookToolbar,
+ when: ContextKeyExpr.and(
+ NOTEBOOK_IS_ACTIVE_EDITOR,
+ NOTEBOOK_LAST_CELL_FAILED,
+ NOTEBOOK_HAS_RUNNING_CELL.toNegated(),
+ ContextKeyExpr.equals('config.notebook.globalToolbar', true)
+ ),
+ group: 'navigation/execute',
+ order: 0
+ },
+ ],
+ icon: icons.errorStateIcon,
+ });
+ }
+
+ async runWithContext(accessor: ServicesAccessor, context: INotebookActionContext): Promise<void> {
+ const notebookExecutionStateService = accessor.get(INotebookExecutionStateService);
+ const notebook = context.notebookEditor.textModel.uri;
+ const lastFailedCellHandle = notebookExecutionStateService.getLastFailedCellForNotebook(notebook);
+ if (lastFailedCellHandle !== undefined) {
+ const lastFailedCell = context.notebookEditor.getCellByHandle(lastFailedCellHandle);
+ if (lastFailedCell) {
+ context.notebookEditor.focusNotebookCell(lastFailedCell, 'container');
+ }
+ }
+ }
+});
diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts
index c0951594b1c..bfaa6a81660 100644
--- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts
+++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts
@@ -232,7 +232,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
keyboardSupport: false,
mouseSupport: true,
multipleSelectionSupport: false,
- enableKeyboardNavigation: true,
+ typeNavigationEnabled: true,
additionalScrollHeight: 0,
// transformOptimization: (isMacintosh && isNative) || getTitleBarStyle(this.configurationService, this.environmentService) === 'native',
styleController: (_suffix: string) => { return this._list!; },
diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts
index 244f65f50ca..e98ae9b79f1 100644
--- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts
+++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts
@@ -445,22 +445,6 @@ export class NotebookTextDiffList extends WorkbenchList<DiffElementViewModelBase
`);
}
- if (styles.listFilterWidgetBackground) {
- content.push(`.monaco-list-type-filter { background-color: ${styles.listFilterWidgetBackground} }`);
- }
-
- if (styles.listFilterWidgetOutline) {
- content.push(`.monaco-list-type-filter { border: 1px solid ${styles.listFilterWidgetOutline}; }`);
- }
-
- if (styles.listFilterWidgetNoMatchesOutline) {
- content.push(`.monaco-list-type-filter.no-matches { border: 1px solid ${styles.listFilterWidgetNoMatchesOutline}; }`);
- }
-
- if (styles.listMatchesShadow) {
- content.push(`.monaco-list-type-filter { box-shadow: 1px 1px 1px ${styles.listMatchesShadow}; }`);
- }
-
const newStyles = content.join('\n');
if (newStyles !== this.styleElement.textContent) {
this.styleElement.textContent = newStyles;
diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebookToolbar.css b/src/vs/workbench/contrib/notebook/browser/media/notebookToolbar.css
index 4b61bafdfd8..f7ddb6665a7 100644
--- a/src/vs/workbench/contrib/notebook/browser/media/notebookToolbar.css
+++ b/src/vs/workbench/contrib/notebook/browser/media/notebookToolbar.css
@@ -80,3 +80,7 @@
.monaco-workbench .notebookOverlay .notebook-toolbar-container .monaco-action-bar:not(.vertical) .action-item.active {
background-color: unset;
}
+
+.monaco-workbench .notebookOverlay .notebook-toolbar-container .monaco-action-bar .action-item .codicon-notebook-state-error {
+ color: var(--notebook-cell-status-icon-error);
+}
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts
index 84614d859fe..9b245482c3d 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts
@@ -325,6 +325,7 @@ export interface INotebookEditorCreationOptions {
readonly menuIds: {
notebookToolbar: MenuId;
cellTitleToolbar: MenuId;
+ cellDeleteToolbar: MenuId;
cellInsertToolbar: MenuId;
cellTopInsertToolbar: MenuId;
cellExecuteToolbar: MenuId;
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
index 99d1d8de1f0..084590f8a0c 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
@@ -33,7 +33,7 @@ import { NotebooKernelActionViewItem } from 'vs/workbench/contrib/notebook/brows
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { NOTEBOOK_EDITOR_ID } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
-import { clearMarks, getAndClearMarks, mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance';
+import { NotebookPerfMarks } from 'vs/workbench/contrib/notebook/common/notebookPerformance';
import { IEditorDropService } from 'vs/workbench/services/editor/browser/editorDropService';
import { GroupsOrder, IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -172,8 +172,8 @@ export class NotebookEditor extends EditorPane implements IEditorPaneWithSelecti
override async setInput(input: NotebookEditorInput, options: INotebookEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken, noRetry?: boolean): Promise<void> {
try {
- clearMarks(input.resource);
- mark(input.resource, 'startTime');
+ const perf = new NotebookPerfMarks();
+ perf.mark('startTime');
const group = this.group!;
this._inputListener.value = input.onDidChangeCapabilities(() => this._onDidChangeInputCapabilities(input));
@@ -203,8 +203,8 @@ export class NotebookEditor extends EditorPane implements IEditorPaneWithSelecti
// only now `setInput` and yield/await. this is AFTER the actual widget is ready. This is very important
// so that others synchronously receive a notebook editor with the correct widget being set
await super.setInput(input, options, context, token);
- const model = await input.resolve();
- mark(input.resource, 'inputLoaded');
+ const model = await input.resolve(perf);
+ perf.mark('inputLoaded');
// Check for cancellation
if (token.isCancellationRequested) {
@@ -230,7 +230,7 @@ export class NotebookEditor extends EditorPane implements IEditorPaneWithSelecti
const viewState = options?.viewState ?? this._loadNotebookEditorViewState(input);
this._widget.value?.setParentContextKeyService(this._contextKeyService);
- await this._widget.value!.setModel(model.notebook, viewState);
+ await this._widget.value!.setModel(model.notebook, viewState, perf);
const isReadOnly = input.hasCapability(EditorInputCapabilities.Readonly);
await this._widget.value!.setOptions({ ...options, isReadOnly });
this._widgetDisposableStore.add(this._widget.value!.onDidFocusWidget(() => this._onDidFocusWidget.fire()));
@@ -240,19 +240,19 @@ export class NotebookEditor extends EditorPane implements IEditorPaneWithSelecti
containsGroup: (group) => this.group?.id === group.id
}));
- mark(input.resource, 'editorLoaded');
+ perf.mark('editorLoaded');
type WorkbenchNotebookOpenClassification = {
owner: 'rebornix';
comment: 'The notebook file open metrics. Used to get a better understanding of the performance of notebook file opening';
- scheme: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
- ext: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
- viewType: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
- extensionActivated: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
- inputLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
- webviewCommLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
- customMarkdownLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
- editorLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
+ scheme: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'File system provider scheme for the notebook resource' };
+ ext: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'File extension for the notebook resource' };
+ viewType: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The view type of the notebook editor' };
+ extensionActivated: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Extension activation time for the resource opening' };
+ inputLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Editor Input loading time for the resource opening' };
+ webviewCommLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Webview initialization time for the resource opening' };
+ customMarkdownLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Custom markdown loading time for the resource opening' };
+ editorLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Overall editor loading time for the resource opening' };
};
type WorkbenchNotebookOpenEvent = {
@@ -266,8 +266,7 @@ export class NotebookEditor extends EditorPane implements IEditorPaneWithSelecti
editorLoaded: number;
};
- const perfMarks = getAndClearMarks(input.resource);
-
+ const perfMarks = perf.value;
if (perfMarks) {
const startTime = perfMarks['startTime'];
const extensionActivated = perfMarks['extensionActivated'];
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
index 3debc2599a6..a3f275365dd 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
@@ -77,7 +77,6 @@ import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/
import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
import { NotebookOptions, OutputInnerContainerTopPadding } from 'vs/workbench/contrib/notebook/common/notebookOptions';
-import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance';
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
import { INotebookRendererMessagingService } from 'vs/workbench/contrib/notebook/common/notebookRendererMessagingService';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
@@ -85,6 +84,7 @@ import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser
import { IWebview } from 'vs/workbench/contrib/webview/browser/webview';
import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
+import { NotebookPerfMarks } from 'vs/workbench/contrib/notebook/common/notebookPerformance';
const $ = DOM.$;
@@ -190,6 +190,7 @@ export function getDefaultNotebookCreationOptions(): INotebookEditorCreationOpti
menuIds: {
notebookToolbar: MenuId.NotebookToolbar,
cellTitleToolbar: MenuId.NotebookCellTitle,
+ cellDeleteToolbar: MenuId.NotebookCellDelete,
cellInsertToolbar: MenuId.NotebookCellBetween,
cellTopInsertToolbar: MenuId.NotebookCellListTop,
cellExecuteToolbar: MenuId.NotebookCellExecute,
@@ -914,7 +915,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
mouseSupport: true,
multipleSelectionSupport: true,
selectionNavigation: true,
- enableKeyboardNavigation: true,
+ typeNavigationEnabled: true,
additionalScrollHeight: 0,
transformOptimization: false, //(isMacintosh && isNative) || getTitleBarStyle(this.configurationService, this.environmentService) === 'native',
styleController: (_suffix: string) => { return this._list; },
@@ -1079,12 +1080,12 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
this.scopedContextKeyService.updateParent(parentContextKeyService);
}
- async setModel(textModel: NotebookTextModel, viewState: INotebookEditorViewState | undefined): Promise<void> {
+ async setModel(textModel: NotebookTextModel, viewState: INotebookEditorViewState | undefined, perf?: NotebookPerfMarks): Promise<void> {
if (this.viewModel === undefined || !this.viewModel.equal(textModel)) {
const oldTopInsertToolbarHeight = this._notebookOptions.computeTopInsertToolbarHeight(this.viewModel?.viewType);
const oldBottomToolbarDimensions = this._notebookOptions.computeBottomToolbarDimensions(this.viewModel?.viewType);
this._detachModel();
- await this._attachModel(textModel, viewState);
+ await this._attachModel(textModel, viewState, perf);
const newTopInsertToolbarHeight = this._notebookOptions.computeTopInsertToolbarHeight(this.viewModel?.viewType);
const newBottomToolbarDimensions = this._notebookOptions.computeBottomToolbarDimensions(this.viewModel?.viewType);
@@ -1101,9 +1102,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
type WorkbenchNotebookOpenClassification = {
owner: 'rebornix';
comment: 'Identify the notebook editor view type';
- scheme: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
- ext: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
- viewType: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
+ scheme: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'File system provider scheme for the resource' };
+ ext: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'File extension for the resource' };
+ viewType: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'View type of the notebook editor' };
};
type WorkbenchNotebookOpenEvent = {
@@ -1388,7 +1389,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
this._list.attachWebview(this._webview.element);
}
- private async _attachModel(textModel: NotebookTextModel, viewState: INotebookEditorViewState | undefined) {
+ private async _attachModel(textModel: NotebookTextModel, viewState: INotebookEditorViewState | undefined, perf?: NotebookPerfMarks) {
await this._createWebview(this.getId(), textModel.uri);
this.viewModel = this.instantiationService.createInstance(NotebookViewModel, textModel.viewType, textModel, this._viewContext, this.getLayoutInfo(), { isReadOnly: this._readOnly });
this._viewContext.eventDispatcher.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]);
@@ -1471,7 +1472,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
// init rendering
await this._warmupWithMarkdownRenderer(this.viewModel, viewState);
- mark(textModel.uri, 'customMarkdownLoaded');
+ perf?.mark('customMarkdownLoaded');
// model attached
this._localCellStateListeners = this.viewModel.viewCells.map(cell => this._bindCellListener(cell));
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookExecutionStateServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookExecutionStateServiceImpl.ts
index e32dbce7ba8..0cf3e56c598 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookExecutionStateServiceImpl.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookExecutionStateServiceImpl.ts
@@ -13,7 +13,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CellEditType, CellUri, ICellEditOperation, NotebookCellExecutionState, NotebookCellInternalMetadata, NotebookTextModelWillAddRemoveEvent } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellExecutionUpdateType, INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
-import { ICellExecuteUpdate, ICellExecutionComplete, ICellExecutionStateChangedEvent, ICellExecutionStateUpdate, INotebookCellExecution, INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
+import { ICellExecuteUpdate, ICellExecutionComplete, ICellExecutionStateChangedEvent, ICellExecutionStateUpdate, INotebookCellExecution, INotebookExecutionStateService, INotebookFailStateChangedEvent } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
export class NotebookExecutionStateService extends Disposable implements INotebookExecutionStateService {
@@ -22,10 +22,14 @@ export class NotebookExecutionStateService extends Disposable implements INotebo
private readonly _executions = new ResourceMap<Map<number, CellExecution>>();
private readonly _notebookListeners = new ResourceMap<NotebookExecutionListeners>();
private readonly _cellListeners = new ResourceMap<IDisposable>();
+ private readonly _lastFailedCells = new ResourceMap<number>();
private readonly _onDidChangeCellExecution = this._register(new Emitter<ICellExecutionStateChangedEvent>());
onDidChangeCellExecution = this._onDidChangeCellExecution.event;
+ private readonly _onDidChangeLastRunFailState = this._register(new Emitter<INotebookFailStateChangedEvent>());
+ onDidChangeLastRunFailState = this._onDidChangeLastRunFailState.event;
+
constructor(
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@ILogService private readonly _logService: ILogService,
@@ -34,6 +38,10 @@ export class NotebookExecutionStateService extends Disposable implements INotebo
super();
}
+ getLastFailedCellForNotebook(notebook: URI): number | undefined {
+ return this._lastFailedCells.get(notebook);
+ }
+
forceCancelNotebookExecutions(notebookUri: URI): void {
const notebookExecutions = this._executions.get(notebookUri);
if (!notebookExecutions) {
@@ -68,7 +76,7 @@ export class NotebookExecutionStateService extends Disposable implements INotebo
this._onDidChangeCellExecution.fire(new NotebookExecutionEvent(notebookUri, cellHandle, exe));
}
- private _onCellExecutionDidComplete(notebookUri: URI, cellHandle: number, exe: CellExecution): void {
+ private _onCellExecutionDidComplete(notebookUri: URI, cellHandle: number, exe: CellExecution, lastRunSuccess?: boolean): void {
const notebookExecutions = this._executions.get(notebookUri);
if (!notebookExecutions) {
this._logService.debug(`NotebookExecutionStateService#_onCellExecutionDidComplete - unknown notebook ${notebookUri.toString()}`);
@@ -86,6 +94,14 @@ export class NotebookExecutionStateService extends Disposable implements INotebo
this._notebookListeners.delete(notebookUri);
}
+ if (lastRunSuccess !== undefined) {
+ if (lastRunSuccess) {
+ this._clearLastFailedCell(notebookUri);
+ } else {
+ this._setLastFailedCell(notebookUri, cellHandle);
+ }
+ }
+
this._onDidChangeCellExecution.fire(new NotebookExecutionEvent(notebookUri, cellHandle));
}
@@ -119,12 +135,22 @@ export class NotebookExecutionStateService extends Disposable implements INotebo
const exe: CellExecution = this._instantiationService.createInstance(CellExecution, cellHandle, notebook);
const disposable = combinedDisposable(
exe.onDidUpdate(() => this._onCellExecutionDidChange(notebookUri, cellHandle, exe)),
- exe.onDidComplete(() => this._onCellExecutionDidComplete(notebookUri, cellHandle, exe)));
+ exe.onDidComplete(lastRunSuccess => this._onCellExecutionDidComplete(notebookUri, cellHandle, exe, lastRunSuccess)));
this._cellListeners.set(CellUri.generate(notebookUri, cellHandle), disposable);
return exe;
}
+ private _setLastFailedCell(notebook: URI, cellHandle: number) {
+ this._lastFailedCells.set(notebook, cellHandle);
+ this._onDidChangeLastRunFailState.fire({ failed: true, notebook });
+ }
+
+ private _clearLastFailedCell(notebook: URI) {
+ this._lastFailedCells.delete(notebook);
+ this._onDidChangeLastRunFailState.fire({ failed: false, notebook: notebook });
+ }
+
override dispose(): void {
super.dispose();
this._executions.forEach(executionMap => {
@@ -250,7 +276,7 @@ class CellExecution extends Disposable implements INotebookCellExecution {
private readonly _onDidUpdate = this._register(new Emitter<void>());
readonly onDidUpdate = this._onDidUpdate.event;
- private readonly _onDidComplete = this._register(new Emitter<void>());
+ private readonly _onDidComplete = this._register(new Emitter<boolean | undefined>());
readonly onDidComplete = this._onDidComplete.event;
private _state: NotebookCellExecutionState = NotebookCellExecutionState.Unconfirmed;
@@ -350,7 +376,7 @@ class CellExecution extends Disposable implements INotebookCellExecution {
this._applyExecutionEdits([edit]);
}
- this._onDidComplete.fire();
+ this._onDidComplete.fire(completionData.lastRunSuccess);
}
private _applyExecutionEdits(edits: ICellEditOperation[]): void {
diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellToolbars.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellToolbars.ts
index 35502e4e1a9..9b3a6397be2 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellToolbars.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellToolbars.ts
@@ -18,7 +18,6 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
-import { DeleteCellAction } from 'vs/workbench/contrib/notebook/browser/controller/editActions';
import { ICellViewModel, INotebookEditorDelegate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/cellParts/cellActionView';
import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
@@ -93,22 +92,23 @@ export interface ICssClassDelegate {
export class CellTitleToolbarPart extends CellPart {
private _toolbar: ToolBar;
- private _deleteToolbar: ToolBar;
private _titleMenu: IMenu;
- private _actionsDisposables = this._register(new DisposableStore());
-
- private _hasActions = false;
+ private _deleteToolbar: ToolBar;
+ private _deleteMenu: IMenu;
+ private _toolbarActionsDisposables = this._register(new DisposableStore());
+ private _deleteActionsDisposables = this._register(new DisposableStore());
private readonly _onDidUpdateActions: Emitter<void> = this._register(new Emitter<void>());
readonly onDidUpdateActions: Event<void> = this._onDidUpdateActions.event;
get hasActions(): boolean {
- return this._hasActions;
+ return this._toolbar.getItemsLength() + this._deleteToolbar.getItemsLength() > 0;
}
constructor(
private readonly toolbarContainer: HTMLElement,
private readonly _rootClassDelegate: ICssClassDelegate,
toolbarId: MenuId,
+ deleteToolbarId: MenuId,
private readonly _notebookEditor: INotebookEditorDelegate,
@IContextKeyService contextKeyService: IContextKeyService,
@IMenuService menuService: IMenuService,
@@ -120,11 +120,14 @@ export class CellTitleToolbarPart extends CellPart {
this._titleMenu = this._register(menuService.createMenu(toolbarId, contextKeyService));
this._deleteToolbar = this._register(instantiationService.invokeFunction(accessor => createToolbar(accessor, toolbarContainer, 'cell-delete-toolbar')));
+ this._deleteMenu = this._register(menuService.createMenu(deleteToolbarId, contextKeyService));
if (!this._notebookEditor.creationOptions.isReadOnly) {
- this._deleteToolbar.setActions([instantiationService.createInstance(DeleteCellAction)]);
+ const deleteActions = getCellToolbarActions(this._deleteMenu);
+ this._deleteToolbar.setActions(deleteActions.primary, deleteActions.secondary);
}
- this.setupChangeListeners();
+ this.setupChangeListeners(this._toolbar, this._titleMenu, this._toolbarActionsDisposables);
+ this.setupChangeListeners(this._deleteToolbar, this._deleteMenu, this._deleteActionsDisposables);
}
override didRenderCell(element: ICellViewModel): void {
@@ -143,22 +146,22 @@ export class CellTitleToolbarPart extends CellPart {
this._deleteToolbar.context = toolbarContext;
}
- private setupChangeListeners(): void {
+ private setupChangeListeners(toolbar: ToolBar, menu: IMenu, actionDisposables: DisposableStore): void {
// #103926
let dropdownIsVisible = false;
let deferredUpdate: (() => void) | undefined;
- this.updateActions();
- this._register(this._titleMenu.onDidChange(() => {
+ this.updateActions(toolbar, menu, actionDisposables);
+ this._register(menu.onDidChange(() => {
if (dropdownIsVisible) {
- deferredUpdate = () => this.updateActions();
+ deferredUpdate = () => this.updateActions(toolbar, menu, actionDisposables);
return;
}
- this.updateActions();
+ this.updateActions(toolbar, menu, actionDisposables);
}));
this._rootClassDelegate.toggle('cell-toolbar-dropdown-active', false);
- this._register(this._toolbar.onDidChangeDropdownVisibility(visible => {
+ this._register(toolbar.onDidChangeDropdownVisibility(visible => {
dropdownIsVisible = visible;
this._rootClassDelegate.toggle('cell-toolbar-dropdown-active', visible);
@@ -172,24 +175,22 @@ export class CellTitleToolbarPart extends CellPart {
}));
}
- private updateActions() {
- this._actionsDisposables.clear();
- const actions = getCellToolbarActions(this._titleMenu);
- this._actionsDisposables.add(actions.disposable);
+ private updateActions(toolbar: ToolBar, menu: IMenu, actionDisposables: DisposableStore) {
+ actionDisposables.clear();
+ const actions = getCellToolbarActions(menu);
+ actionDisposables.add(actions.disposable);
- const hadFocus = DOM.isAncestor(document.activeElement, this._toolbar.getElement());
- this._toolbar.setActions(actions.primary, actions.secondary);
+ const hadFocus = DOM.isAncestor(document.activeElement, toolbar.getElement());
+ toolbar.setActions(actions.primary, actions.secondary);
if (hadFocus) {
this._notebookEditor.focus();
}
if (actions.primary.length || actions.secondary.length) {
this._rootClassDelegate.toggle('cell-has-toolbar-actions', true);
- this._hasActions = true;
this._onDidUpdateActions.fire();
} else {
this._rootClassDelegate.toggle('cell-has-toolbar-actions', false);
- this._hasActions = false;
this._onDidUpdateActions.fire();
}
}
diff --git a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts
index b62e89274d0..ace2ec61b1b 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts
@@ -1393,22 +1393,6 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
`);
}
- if (styles.listFilterWidgetBackground) {
- content.push(`.monaco-list-type-filter { background-color: ${styles.listFilterWidgetBackground} }`);
- }
-
- if (styles.listFilterWidgetOutline) {
- content.push(`.monaco-list-type-filter { border: 1px solid ${styles.listFilterWidgetOutline}; }`);
- }
-
- if (styles.listFilterWidgetNoMatchesOutline) {
- content.push(`.monaco-list-type-filter.no-matches { border: 1px solid ${styles.listFilterWidgetNoMatchesOutline}; }`);
- }
-
- if (styles.listMatchesShadow) {
- content.push(`.monaco-list-type-filter { box-shadow: 1px 1px 1px ${styles.listMatchesShadow}; }`);
- }
-
const newStyles = content.join('\n');
if (newStyles !== this.styleElement.textContent) {
this.styleElement.textContent = newStyles;
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 2bcf55c8531..77ed53a9ce3 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts
@@ -160,6 +160,7 @@ export class MarkupCellRenderer extends AbstractCellRenderer implements IListRen
titleToolbarContainer,
rootClassDelegate,
this.notebookEditor.creationOptions.menuIds.cellTitleToolbar,
+ this.notebookEditor.creationOptions.menuIds.cellDeleteToolbar,
this.notebookEditor));
const focusIndicatorBottom = new FastDomNode(DOM.append(container, $('.cell-focus-indicator.cell-focus-indicator-bottom')));
@@ -299,6 +300,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
titleToolbarContainer,
rootClassDelegate,
this.notebookEditor.creationOptions.menuIds.cellTitleToolbar,
+ this.notebookEditor.creationOptions.menuIds.cellDeleteToolbar,
this.notebookEditor));
const focusIndicatorPart = templateDisposables.add(new CellFocusIndicator(this.notebookEditor, titleToolbar, focusIndicatorTop, focusIndicatorLeft, focusIndicatorRight, focusIndicatorBottom));
diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts
index 3702ac26261..27384f830d4 100644
--- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts
+++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts
@@ -6,8 +6,8 @@
import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ICellViewModel, INotebookEditorDelegate, KERNEL_EXTENSIONS } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
-import { NOTEBOOK_CELL_TOOLBAR_LOCATION, NOTEBOOK_HAS_OUTPUTS, NOTEBOOK_HAS_RUNNING_CELL, NOTEBOOK_INTERRUPTIBLE_KERNEL, NOTEBOOK_KERNEL, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_KERNEL_SELECTED, NOTEBOOK_KERNEL_SOURCE_COUNT, NOTEBOOK_MISSING_KERNEL_EXTENSION, NOTEBOOK_USE_CONSOLIDATED_OUTPUT_BUTTON, NOTEBOOK_VIEW_TYPE } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
-import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
+import { NOTEBOOK_CELL_TOOLBAR_LOCATION, NOTEBOOK_HAS_OUTPUTS, NOTEBOOK_HAS_RUNNING_CELL, NOTEBOOK_INTERRUPTIBLE_KERNEL, NOTEBOOK_KERNEL, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_KERNEL_SELECTED, NOTEBOOK_KERNEL_SOURCE_COUNT, NOTEBOOK_LAST_CELL_FAILED, NOTEBOOK_MISSING_KERNEL_EXTENSION, NOTEBOOK_USE_CONSOLIDATED_OUTPUT_BUTTON, NOTEBOOK_VIEW_TYPE } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
+import { INotebookExecutionStateService, INotebookFailStateChangedEvent } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
@@ -24,6 +24,7 @@ export class NotebookEditorContextKeys {
private readonly _viewType!: IContextKey<string>;
private readonly _missingKernelExtension: IContextKey<boolean>;
private readonly _cellToolbarLocation: IContextKey<'left' | 'right' | 'hidden'>;
+ private readonly _lastCellFailed: IContextKey<boolean>;
private readonly _disposables = new DisposableStore();
private readonly _viewModelDisposables = new DisposableStore();
@@ -47,6 +48,7 @@ export class NotebookEditorContextKeys {
this._missingKernelExtension = NOTEBOOK_MISSING_KERNEL_EXTENSION.bindTo(contextKeyService);
this._notebookKernelSourceCount = NOTEBOOK_KERNEL_SOURCE_COUNT.bindTo(contextKeyService);
this._cellToolbarLocation = NOTEBOOK_CELL_TOOLBAR_LOCATION.bindTo(contextKeyService);
+ this._lastCellFailed = NOTEBOOK_LAST_CELL_FAILED.bindTo(contextKeyService);
this._handleDidChangeModel();
this._updateForNotebookOptions();
@@ -58,6 +60,7 @@ export class NotebookEditorContextKeys {
this._disposables.add(_editor.notebookOptions.onDidChangeOptions(this._updateForNotebookOptions, this));
this._disposables.add(_extensionService.onDidChangeExtensions(this._updateForInstalledExtension, this));
this._disposables.add(_notebookExecutionStateService.onDidChangeCellExecution(this._updateForCellExecution, this));
+ this._disposables.add(_notebookExecutionStateService.onDidChangeLastRunFailState(this._updateForLastRunFailState, this));
}
dispose(): void {
@@ -132,6 +135,12 @@ export class NotebookEditorContextKeys {
}
}
+ private _updateForLastRunFailState(e: INotebookFailStateChangedEvent): void {
+ if (e.notebook === this._editor.textModel?.uri) {
+ this._lastCellFailed.set(e.failed);
+ }
+ }
+
private async _updateForInstalledExtension(): Promise<void> {
if (!this._editor.hasModel()) {
return;
diff --git a/src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts b/src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts
index e629ed034d2..fd9692eba0f 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts
@@ -24,6 +24,7 @@ export const NOTEBOOK_USE_CONSOLIDATED_OUTPUT_BUTTON = new RawContextKey<boolean
export const NOTEBOOK_BREAKPOINT_MARGIN_ACTIVE = new RawContextKey<boolean>('notebookBreakpointMargin', false);
export const NOTEBOOK_CELL_TOOLBAR_LOCATION = new RawContextKey<'left' | 'right' | 'hidden'>('notebookCellToolbarLocation', 'left');
export const NOTEBOOK_CURSOR_NAVIGATION_MODE = new RawContextKey<boolean>('notebookCursorNavigationMode', false);
+export const NOTEBOOK_LAST_CELL_FAILED = new RawContextKey<boolean>('notebookLastCellFailed', false);
// Cell keys
export const NOTEBOOK_VIEW_TYPE = new RawContextKey<string>('notebookType', undefined);
diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts
index b8cbd4985d0..54e0ac40f5e 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts
@@ -16,7 +16,6 @@ import { IDisposable, IReference } from 'vs/base/common/lifecycle';
import { CellEditType, IResolvedNotebookEditorModel } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { ILabelService } from 'vs/platform/label/common/label';
import { Schemas } from 'vs/base/common/network';
-import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance';
import { FileSystemProviderCapabilities, IFileService } from 'vs/platform/files/common/files';
import { AbstractResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
import { IResourceEditorInput } from 'vs/platform/editor/common/editor';
@@ -24,6 +23,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
import { VSBuffer } from 'vs/base/common/buffer';
import { IWorkingCopyIdentifier } from 'vs/workbench/services/workingCopy/common/workingCopy';
import { NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
+import { NotebookPerfMarks } from 'vs/workbench/contrib/notebook/common/notebookPerformance';
export interface NotebookEditorInputOptions {
startDirty?: boolean;
@@ -231,12 +231,12 @@ export class NotebookEditorInput extends AbstractResourceEditorInput {
}
}
- override async resolve(): Promise<IResolvedNotebookEditorModel | null> {
+ override async resolve(perf?: NotebookPerfMarks): Promise<IResolvedNotebookEditorModel | null> {
if (!await this._notebookService.canResolve(this.viewType)) {
return null;
}
- mark(this.resource, 'extensionActivated');
+ perf?.mark('extensionActivated');
// we are now loading the notebook and don't need to listen to
// "other" loading anymore
diff --git a/src/vs/workbench/contrib/notebook/common/notebookExecutionStateService.ts b/src/vs/workbench/contrib/notebook/common/notebookExecutionStateService.ts
index f6317245bb1..d1fbe75907f 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookExecutionStateService.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookExecutionStateService.ts
@@ -39,6 +39,10 @@ export interface ICellExecutionStateChangedEvent {
affectsCell(cell: URI): boolean;
affectsNotebook(notebook: URI): boolean;
}
+export interface INotebookFailStateChangedEvent {
+ failed: boolean;
+ notebook: URI;
+}
export const INotebookExecutionStateService = createDecorator<INotebookExecutionStateService>('INotebookExecutionStateService');
@@ -46,11 +50,13 @@ export interface INotebookExecutionStateService {
_serviceBrand: undefined;
onDidChangeCellExecution: Event<ICellExecutionStateChangedEvent>;
+ onDidChangeLastRunFailState: Event<INotebookFailStateChangedEvent>;
forceCancelNotebookExecutions(notebookUri: URI): void;
getCellExecutionStatesForNotebook(notebook: URI): INotebookCellExecution[];
getCellExecution(cellUri: URI): INotebookCellExecution | undefined;
createCellExecution(notebook: URI, cellHandle: number): INotebookCellExecution;
+ getLastFailedCellForNotebook(notebook: URI): number | undefined;
}
export interface INotebookCellExecution {
diff --git a/src/vs/workbench/contrib/notebook/common/notebookPerformance.ts b/src/vs/workbench/contrib/notebook/common/notebookPerformance.ts
index bd59c7bfbf1..c47b6eeeb2c 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookPerformance.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookPerformance.ts
@@ -3,39 +3,23 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { URI } from 'vs/base/common/uri';
-
export type PerfName = 'startTime' | 'extensionActivated' | 'inputLoaded' | 'webviewCommLoaded' | 'customMarkdownLoaded' | 'editorLoaded';
type PerformanceMark = { [key in PerfName]?: number };
-const perfMarks = new Map<string, PerformanceMark>();
+export class NotebookPerfMarks {
+ private _marks: PerformanceMark = {};
+
+ get value(): PerformanceMark {
+ return { ...this._marks };
+ }
-export function mark(resource: URI, name: PerfName): void {
- const key = resource.toString();
- if (!perfMarks.has(key)) {
- const perfMark: PerformanceMark = {};
- perfMark[name] = Date.now();
- perfMarks.set(key, perfMark);
- } else {
- if (perfMarks.get(key)![name]) {
+ mark(name: PerfName): void {
+ if (this._marks[name]) {
console.error(`Skipping overwrite of notebook perf value: ${name}`);
return;
}
- perfMarks.get(key)![name] = Date.now();
- }
-}
-export function clearMarks(resource: URI): void {
- const key = resource.toString();
-
- perfMarks.delete(key);
-}
-
-export function getAndClearMarks(resource: URI): PerformanceMark | null {
- const key = resource.toString();
-
- const perfMark = perfMarks.get(key) || null;
- perfMarks.delete(key);
- return perfMark;
+ this._marks[name] = Date.now();
+ }
}
diff --git a/src/vs/workbench/contrib/notebook/test/browser/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/browser/testNotebookEditor.ts
index 8570bf9146a..1d667408085 100644
--- a/src/vs/workbench/contrib/notebook/test/browser/testNotebookEditor.ts
+++ b/src/vs/workbench/contrib/notebook/test/browser/testNotebookEditor.ts
@@ -44,7 +44,7 @@ import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/vie
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CellKind, CellUri, INotebookDiffEditorModel, INotebookEditorModel, INotebookSearchOptions, IOutputDto, IResolvedNotebookEditorModel, NotebookCellExecutionState, NotebookCellMetadata, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
-import { ICellExecuteUpdate, ICellExecutionComplete, ICellExecutionStateChangedEvent, INotebookCellExecution, INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
+import { ICellExecuteUpdate, ICellExecutionComplete, ICellExecutionStateChangedEvent, INotebookCellExecution, INotebookExecutionStateService, INotebookFailStateChangedEvent } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
@@ -366,7 +366,6 @@ export function createNotebookCellList(instantiationService: TestInstantiationSe
{
supportDynamicHeights: true,
multipleSelectionSupport: true,
- enableKeyboardNavigation: true,
focusNextPreviousDelegate: {
onFocusNext: (applyFocusNext: () => void) => { applyFocusNext(); },
onFocusPrevious: (applyFocusPrevious: () => void) => { applyFocusPrevious(); },
@@ -405,11 +404,17 @@ class TestCellExecution implements INotebookCellExecution {
}
class TestNotebookExecutionStateService implements INotebookExecutionStateService {
+
+ getLastFailedCellForNotebook(notebook: URI): number | undefined {
+ return;
+ }
+
_serviceBrand: undefined;
private _executions = new ResourceMap<INotebookCellExecution>();
onDidChangeCellExecution = new Emitter<ICellExecutionStateChangedEvent>().event;
+ onDidChangeLastRunFailState = new Emitter<INotebookFailStateChangedEvent>().event;
forceCancelNotebookExecutions(notebookUri: URI): void {
}