Skip to content

Commit

Permalink
Show cell execution state when collapsed. Fix #131200
Browse files Browse the repository at this point in the history
  • Loading branch information
roblourens committed Feb 11, 2022
1 parent 1d9e655 commit 679fc19
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 5 deletions.
15 changes: 15 additions & 0 deletions src/vs/workbench/contrib/notebook/browser/media/notebook.css
Original file line number Diff line number Diff line change
Expand Up @@ -341,11 +341,26 @@
}

.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .input-collapse-container {
display: flex;
align-items: center;
position: relative;
box-sizing: border-box;
width: 100%;
}

.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .input-collapse-container .collapsed-execution-icon {
line-height: normal;
margin-left: 6px;
}

.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .input-collapse-container .collapsed-execution-icon .codicon-notebook-state-success {
color: var(--notebook-cell-status-icon-success);
}

.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .input-collapse-container .collapsed-execution-icon .codicon-notebook-state-error {
color: var(--notebook-cell-status-icon-error);
}

.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .input-collapse-container .cell-collapse-preview {
padding: 0px 8px;
display: flex;
Expand Down
11 changes: 11 additions & 0 deletions src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3072,6 +3072,17 @@ registerThemingParticipant((theme, collector) => {
}
`);

const cellStatusIconSuccessColor = theme.getColor(cellStatusIconSuccess);
const cellStatusIconErrorColor = theme.getColor(cellStatusIconError);
const cellStatusIconRunningColor = theme.getColor(cellStatusIconRunning);
collector.addRule(`
:root {
--notebook-cell-status-icon-success: ${cellStatusIconSuccessColor};
--notebook-cell-status-icon-error: ${cellStatusIconErrorColor};
--notebook-cell-status-icon-running: ${cellStatusIconRunningColor};
}
`);

const link = theme.getColor(textLinkForeground);
if (link) {
collector.addRule(`.notebookOverlay .cell.markdown a,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import { raceCancellation } from 'vs/base/common/async';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { Codicon, CSSIcon } from 'vs/base/common/codicons';
import { Event } from 'vs/base/common/event';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { IDimension } from 'vs/editor/common/core/dimension';
import { IReadonlyTextBuffer } from 'vs/editor/common/model';
import { tokenizeToStringSync } from 'vs/editor/common/languages/textToHtmlTokenizer';
import { ILanguageService } from 'vs/editor/common/languages/language';
import { tokenizeToStringSync } from 'vs/editor/common/languages/textToHtmlTokenizer';
import { IReadonlyTextBuffer } from 'vs/editor/common/model';
import { localize } from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
Expand All @@ -24,6 +24,7 @@ import { CellEditorOptions } from 'vs/workbench/contrib/notebook/browser/view/ce
import { CellOutputContainer } from 'vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput';
import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellParts/cellPart';
import { ClickTargetType } from 'vs/workbench/contrib/notebook/browser/view/cellParts/cellWidgets';
import { CodeCellExecutionIcon } from 'vs/workbench/contrib/notebook/browser/view/cellParts/codeCellExecutionIcon';
import { CodeCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/view/notebookRenderingCommon';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService';
Expand All @@ -38,6 +39,8 @@ export class CodeCell extends Disposable {
private _isDisposed: boolean = false;
private readonly cellParts: CellPart[];

private _collapsedExecutionIcon: CodeCellExecutionIcon;

constructor(
private readonly notebookEditor: IActiveNotebookEditorDelegate,
private readonly viewCell: CodeCellViewModel,
Expand Down Expand Up @@ -125,6 +128,11 @@ export class CodeCell extends Disposable {
this.cellParts.forEach(cellPart => cellPart.prepareLayout());
}));

const executionItemElement = DOM.append(this.templateData.cellInputCollapsedContainer, DOM.$('.collapsed-execution-icon'));
this._register(toDisposable(() => {
executionItemElement.parentElement?.removeChild(executionItemElement);
}));
this._collapsedExecutionIcon = this.instantiationService.createInstance(CodeCellExecutionIcon, this.notebookEditor, this.viewCell, executionItemElement);
this.updateForCollapseState();

this._register(Event.runAndSubscribe(viewCell.onDidChangeOutputs, this.updateForOutputs.bind(this)));
Expand Down Expand Up @@ -387,10 +395,11 @@ export class CodeCell extends Disposable {
// remove input preview
this._removeInputCollapsePreview();

this._collapsedExecutionIcon.setVisibility(true);

// update preview
const richEditorText = this._getRichText(this.viewCell.textBuffer, this.viewCell.language);
const element = DOM.$('div');
element.classList.add('cell-collapse-preview');
const element = DOM.$('div.cell-collapse-preview');
DOM.safeInnerHtml(element, richEditorText);
this.templateData.cellInputCollapsedContainer.appendChild(element);
const expandIcon = DOM.$('span.expandInputIcon');
Expand All @@ -407,6 +416,7 @@ export class CodeCell extends Disposable {
}

private _showInput() {
this._collapsedExecutionIcon.setVisibility(false);
DOM.show(this.templateData.editorPart);
DOM.hide(this.templateData.cellInputCollapsedContainer);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as DOM from 'vs/base/browser/dom';
import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
import { Disposable } from 'vs/base/common/lifecycle';
import { localize } from 'vs/nls';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { ICellViewModel, INotebookEditorDelegate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { errorStateIcon, executingStateIcon, pendingStateIcon, successStateIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons';
import { NotebookCellExecutionState, NotebookCellInternalMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookCellExecution, INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';

interface IExecutionItem {
text: string;
tooltip?: string;
}

export class CodeCellExecutionIcon extends Disposable {
private _visible = false;

constructor(
_notebookEditor: INotebookEditorDelegate,
private readonly _cell: ICellViewModel,
private readonly _element: HTMLElement,
@INotebookExecutionStateService private _executionStateService: INotebookExecutionStateService,
) {
super();

this._update();
this._register(this._executionStateService.onDidChangeCellExecution(e => {
if (e.affectsCell(this._cell.uri)) {
this._update();
}
}));
this._register(this._cell.model.onDidChangeInternalMetadata(() => this._update()));
}

setVisibility(visible: boolean): void {
this._visible = visible;
this._update();
}

private _update() {
if (!this._visible) {
return;
}

const runState = this._executionStateService.getCellExecution(this._cell.uri);
const item = this._getItemForState(runState, this._cell.model.internalMetadata);
if (item) {
this._element.style.display = '';
DOM.reset(this._element, ...renderLabelWithIcons(item.text));
this._element.title = item.tooltip ?? '';
} else {
this._element.style.display = 'none';
DOM.reset(this._element);
}
}

private _getItemForState(runState: INotebookCellExecution | undefined, internalMetadata: NotebookCellInternalMetadata): IExecutionItem | undefined {
const state = runState?.state;
const { lastRunSuccess } = internalMetadata;
if (!state && lastRunSuccess) {
return <IExecutionItem>{
text: `$(${successStateIcon.id})`,
tooltip: localize('notebook.cell.status.success', "Success"),
};
} else if (!state && lastRunSuccess === false) {
return <IExecutionItem>{
text: `$(${errorStateIcon.id})`,
tooltip: localize('notebook.cell.status.failed', "Failed"),
};
} else if (state === NotebookCellExecutionState.Pending) {
return <IExecutionItem>{
text: `$(${pendingStateIcon.id})`,
tooltip: localize('notebook.cell.status.pending', "Pending"),
};
} else if (state === NotebookCellExecutionState.Executing) {
const icon = runState?.isPaused ?
executingStateIcon :
ThemeIcon.modify(executingStateIcon, 'spin');
return <IExecutionItem>{
text: `$(${icon.id})`,
tooltip: localize('notebook.cell.status.executing', "Executing"),
};
}

return;
}
}

0 comments on commit 679fc19

Please sign in to comment.