@theia/notebook 1.55.0-next.4 → 1.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts.map +1 -1
- package/lib/browser/contributions/notebook-cell-actions-contribution.js +55 -10
- package/lib/browser/contributions/notebook-cell-actions-contribution.js.map +1 -1
- package/lib/browser/contributions/notebook-status-bar-contribution.d.ts +7 -9
- package/lib/browser/contributions/notebook-status-bar-contribution.d.ts.map +1 -1
- package/lib/browser/contributions/notebook-status-bar-contribution.js +21 -33
- package/lib/browser/contributions/notebook-status-bar-contribution.js.map +1 -1
- package/lib/browser/notebook-editor-widget.d.ts +4 -0
- package/lib/browser/notebook-editor-widget.d.ts.map +1 -1
- package/lib/browser/notebook-editor-widget.js +23 -1
- package/lib/browser/notebook-editor-widget.js.map +1 -1
- package/lib/browser/notebook-frontend-module.d.ts.map +1 -1
- package/lib/browser/notebook-frontend-module.js +3 -1
- package/lib/browser/notebook-frontend-module.js.map +1 -1
- package/lib/browser/renderers/cell-output-webview.d.ts +17 -3
- package/lib/browser/renderers/cell-output-webview.d.ts.map +1 -1
- package/lib/browser/renderers/cell-output-webview.js +2 -1
- package/lib/browser/renderers/cell-output-webview.js.map +1 -1
- package/lib/browser/service/notebook-cell-editor-service.d.ts +3 -0
- package/lib/browser/service/notebook-cell-editor-service.d.ts.map +1 -1
- package/lib/browser/service/notebook-cell-editor-service.js +26 -2
- package/lib/browser/service/notebook-cell-editor-service.js.map +1 -1
- package/lib/browser/service/notebook-cell-status-bar-service.d.ts +39 -0
- package/lib/browser/service/notebook-cell-status-bar-service.d.ts.map +1 -0
- package/lib/browser/service/notebook-cell-status-bar-service.js +69 -0
- package/lib/browser/service/notebook-cell-status-bar-service.js.map +1 -0
- package/lib/browser/service/notebook-editor-widget-service.d.ts +4 -0
- package/lib/browser/service/notebook-editor-widget-service.d.ts.map +1 -1
- package/lib/browser/service/notebook-editor-widget-service.js +19 -0
- package/lib/browser/service/notebook-editor-widget-service.js.map +1 -1
- package/lib/browser/view/notebook-cell-editor.d.ts +1 -0
- package/lib/browser/view/notebook-cell-editor.d.ts.map +1 -1
- package/lib/browser/view/notebook-cell-editor.js +19 -13
- package/lib/browser/view/notebook-cell-editor.js.map +1 -1
- package/lib/browser/view/notebook-cell-list-view.d.ts +4 -1
- package/lib/browser/view/notebook-cell-list-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-cell-list-view.js +36 -13
- package/lib/browser/view/notebook-cell-list-view.js.map +1 -1
- package/lib/browser/view/notebook-cell-toolbar.js +1 -1
- package/lib/browser/view/notebook-cell-toolbar.js.map +1 -1
- package/lib/browser/view/notebook-code-cell-view.d.ts +30 -12
- package/lib/browser/view/notebook-code-cell-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-code-cell-view.js +99 -71
- package/lib/browser/view/notebook-code-cell-view.js.map +1 -1
- package/lib/browser/view/notebook-main-toolbar.js +4 -4
- package/lib/browser/view/notebook-main-toolbar.js.map +1 -1
- package/lib/browser/view/notebook-markdown-cell-view.d.ts +5 -0
- package/lib/browser/view/notebook-markdown-cell-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-markdown-cell-view.js +22 -5
- package/lib/browser/view/notebook-markdown-cell-view.js.map +1 -1
- package/lib/browser/view-model/notebook-cell-model.d.ts +12 -0
- package/lib/browser/view-model/notebook-cell-model.d.ts.map +1 -1
- package/lib/browser/view-model/notebook-cell-model.js +19 -0
- package/lib/browser/view-model/notebook-cell-model.js.map +1 -1
- package/lib/browser/view-model/notebook-cell-output-model.d.ts +0 -3
- package/lib/browser/view-model/notebook-cell-output-model.d.ts.map +1 -1
- package/lib/browser/view-model/notebook-cell-output-model.js +0 -6
- package/lib/browser/view-model/notebook-cell-output-model.js.map +1 -1
- package/lib/browser/view-model/notebook-model.d.ts +2 -1
- package/lib/browser/view-model/notebook-model.d.ts.map +1 -1
- package/lib/browser/view-model/notebook-model.js +3 -0
- package/lib/browser/view-model/notebook-model.js.map +1 -1
- package/package.json +8 -8
- package/src/browser/contributions/notebook-cell-actions-contribution.ts +61 -11
- package/src/browser/contributions/notebook-status-bar-contribution.ts +23 -34
- package/src/browser/notebook-editor-widget.tsx +32 -7
- package/src/browser/notebook-frontend-module.ts +6 -2
- package/src/browser/renderers/cell-output-webview.ts +21 -3
- package/src/browser/service/notebook-cell-editor-service.ts +21 -3
- package/src/browser/service/notebook-cell-status-bar-service.ts +94 -0
- package/src/browser/service/notebook-editor-widget-service.ts +20 -0
- package/src/browser/style/index.css +54 -9
- package/src/browser/view/notebook-cell-editor.tsx +18 -11
- package/src/browser/view/notebook-cell-list-view.tsx +44 -13
- package/src/browser/view/notebook-cell-toolbar.tsx +1 -1
- package/src/browser/view/notebook-code-cell-view.tsx +143 -92
- package/src/browser/view/notebook-main-toolbar.tsx +4 -4
- package/src/browser/view/notebook-markdown-cell-view.tsx +30 -6
- package/src/browser/view-model/notebook-cell-model.ts +29 -0
- package/src/browser/view-model/notebook-cell-output-model.ts +0 -8
- package/src/browser/view-model/notebook-model.ts +5 -1
|
@@ -14,10 +14,9 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
17
|
+
import { injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import { StatusBar, StatusBarAlignment, Widget, WidgetStatusBarContribution } from '@theia/core/lib/browser';
|
|
19
19
|
import { Disposable } from '@theia/core/lib/common';
|
|
20
|
-
import { NotebookEditorWidgetService } from '../service/notebook-editor-widget-service';
|
|
21
20
|
import { NotebookEditorWidget } from '../notebook-editor-widget';
|
|
22
21
|
import { nls } from '@theia/core';
|
|
23
22
|
import { NotebookCommands } from './notebook-actions-contribution';
|
|
@@ -25,53 +24,43 @@ import { NotebookCommands } from './notebook-actions-contribution';
|
|
|
25
24
|
export const NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID = 'notebook-cell-selection-position';
|
|
26
25
|
|
|
27
26
|
@injectable()
|
|
28
|
-
export class NotebookStatusBarContribution implements
|
|
27
|
+
export class NotebookStatusBarContribution implements WidgetStatusBarContribution<NotebookEditorWidget> {
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
@inject(NotebookEditorWidgetService) protected readonly editorWidgetService: NotebookEditorWidgetService;
|
|
29
|
+
protected onDeactivate: Disposable | undefined;
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
canHandle(widget: Widget): widget is NotebookEditorWidget {
|
|
32
|
+
return widget instanceof NotebookEditorWidget;
|
|
33
|
+
}
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
this.
|
|
39
|
-
|
|
40
|
-
this.updateStatusbar(editor)
|
|
41
|
-
);
|
|
42
|
-
editor?.onDidDispose(() => {
|
|
43
|
-
this.lastFocusedEditor = undefined;
|
|
44
|
-
this.updateStatusbar();
|
|
35
|
+
activate(statusBar: StatusBar, widget: NotebookEditorWidget): void {
|
|
36
|
+
widget.ready.then(model => {
|
|
37
|
+
this.onDeactivate = model.onDidChangeSelectedCell(() => {
|
|
38
|
+
this.updateStatusbar(statusBar, widget);
|
|
45
39
|
});
|
|
46
|
-
this.updateStatusbar(editor);
|
|
47
|
-
this.lastFocusedEditor = editor;
|
|
48
40
|
});
|
|
49
|
-
|
|
50
|
-
this.updateStatusbar();
|
|
51
|
-
}
|
|
41
|
+
this.updateStatusbar(statusBar, widget);
|
|
52
42
|
}
|
|
53
43
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
44
|
+
deactivate(statusBar: StatusBar): void {
|
|
45
|
+
this.onDeactivate?.dispose();
|
|
46
|
+
this.updateStatusbar(statusBar);
|
|
47
|
+
}
|
|
59
48
|
|
|
60
|
-
|
|
61
|
-
|
|
49
|
+
protected async updateStatusbar(statusBar: StatusBar, editor?: NotebookEditorWidget): Promise<void> {
|
|
50
|
+
const model = await editor?.ready;
|
|
51
|
+
if (!model || model.cells.length === 0 || !model.selectedCell) {
|
|
52
|
+
statusBar.removeElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID);
|
|
62
53
|
return;
|
|
63
54
|
}
|
|
64
55
|
|
|
65
|
-
const selectedCellIndex =
|
|
56
|
+
const selectedCellIndex = model.cells.indexOf(model.selectedCell) + 1;
|
|
66
57
|
|
|
67
|
-
|
|
68
|
-
text: nls.localizeByDefault('Cell {0} of {1}', selectedCellIndex,
|
|
58
|
+
statusBar.setElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID, {
|
|
59
|
+
text: nls.localizeByDefault('Cell {0} of {1}', selectedCellIndex, model.cells.length),
|
|
69
60
|
alignment: StatusBarAlignment.RIGHT,
|
|
70
61
|
priority: 100,
|
|
71
62
|
command: NotebookCommands.CENTER_ACTIVE_CELL.id,
|
|
72
63
|
arguments: [editor]
|
|
73
64
|
});
|
|
74
|
-
|
|
75
65
|
}
|
|
76
|
-
|
|
77
66
|
}
|
|
@@ -18,7 +18,7 @@ import * as React from '@theia/core/shared/react';
|
|
|
18
18
|
import { CommandRegistry, MenuModelRegistry, URI } from '@theia/core';
|
|
19
19
|
import { ReactWidget, Navigatable, SaveableSource, Message, DelegatingSaveable, lock, unlock, animationFrame } from '@theia/core/lib/browser';
|
|
20
20
|
import { ReactNode } from '@theia/core/shared/react';
|
|
21
|
-
import { CellKind } from '../common';
|
|
21
|
+
import { CellKind, NotebookCellsChangeType } from '../common';
|
|
22
22
|
import { CellRenderer as CellRenderer, NotebookCellListView } from './view/notebook-cell-list-view';
|
|
23
23
|
import { NotebookCodeCellRenderer } from './view/notebook-code-cell-view';
|
|
24
24
|
import { NotebookMarkdownCellRenderer } from './view/notebook-markdown-cell-view';
|
|
@@ -35,6 +35,8 @@ import { NotebookViewportService } from './view/notebook-viewport-service';
|
|
|
35
35
|
import { NotebookCellCommands } from './contributions/notebook-cell-actions-contribution';
|
|
36
36
|
import { NotebookFindWidget } from './view/notebook-find-widget';
|
|
37
37
|
import debounce = require('lodash/debounce');
|
|
38
|
+
import { CellOutputWebview, CellOutputWebviewFactory } from './renderers/cell-output-webview';
|
|
39
|
+
import { NotebookCellOutputModel } from './view-model/notebook-cell-output-model';
|
|
38
40
|
const PerfectScrollbar = require('react-perfect-scrollbar');
|
|
39
41
|
|
|
40
42
|
export const NotebookEditorWidgetContainerFactory = Symbol('NotebookEditorWidgetContainerFactory');
|
|
@@ -44,6 +46,9 @@ export function createNotebookEditorWidgetContainer(parent: interfaces.Container
|
|
|
44
46
|
|
|
45
47
|
child.bind(NotebookEditorProps).toConstantValue(props);
|
|
46
48
|
|
|
49
|
+
const cellOutputWebviewFactory: CellOutputWebviewFactory = parent.get(CellOutputWebviewFactory);
|
|
50
|
+
child.bind(CellOutputWebview).toConstantValue(cellOutputWebviewFactory());
|
|
51
|
+
|
|
47
52
|
child.bind(NotebookContextManager).toSelf().inSingletonScope();
|
|
48
53
|
child.bind(NotebookMainToolbarRenderer).toSelf().inSingletonScope();
|
|
49
54
|
child.bind(NotebookCellToolbarFactory).toSelf().inSingletonScope();
|
|
@@ -104,6 +109,9 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
104
109
|
@inject(NotebookViewportService)
|
|
105
110
|
protected readonly viewportService: NotebookViewportService;
|
|
106
111
|
|
|
112
|
+
@inject(CellOutputWebview)
|
|
113
|
+
protected readonly cellOutputWebview: CellOutputWebview;
|
|
114
|
+
|
|
107
115
|
protected readonly onDidChangeModelEmitter = new Emitter<void>();
|
|
108
116
|
readonly onDidChangeModel = this.onDidChangeModelEmitter.event;
|
|
109
117
|
|
|
@@ -173,11 +181,18 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
173
181
|
this.commandRegistry.executeCommand(NotebookCellCommands.EDIT_COMMAND.id, model, model.cells[0]);
|
|
174
182
|
model.setSelectedCell(model.cells[0]);
|
|
175
183
|
}
|
|
184
|
+
model.onDidChangeContent(changeEvents => {
|
|
185
|
+
const cellEvent = changeEvents.filter(event => event.kind === NotebookCellsChangeType.Move || event.kind === NotebookCellsChangeType.ModelChange);
|
|
186
|
+
if (cellEvent.length > 0) {
|
|
187
|
+
this.cellOutputWebview.cellsChanged(cellEvent);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
176
190
|
});
|
|
177
191
|
}
|
|
178
192
|
|
|
179
193
|
protected async waitForData(): Promise<NotebookModel> {
|
|
180
194
|
this._model = await this.props.notebookData;
|
|
195
|
+
this.cellOutputWebview.init(this._model, this);
|
|
181
196
|
this.saveable.delegate = this._model;
|
|
182
197
|
this.toDispose.push(this._model);
|
|
183
198
|
this.toDispose.push(this._model.onDidChangeContent(() => {
|
|
@@ -261,12 +276,15 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
261
276
|
<PerfectScrollbar className='theia-notebook-scroll-container'
|
|
262
277
|
ref={this.scrollBarRef}
|
|
263
278
|
onScrollY={(e: HTMLDivElement) => this.viewportService.onScroll(e)}>
|
|
264
|
-
<
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
279
|
+
<div className='theia-notebook-scroll-area'>
|
|
280
|
+
{this.cellOutputWebview.render()}
|
|
281
|
+
<NotebookCellListView renderers={this.renderers}
|
|
282
|
+
notebookModel={this._model}
|
|
283
|
+
notebookContext={this.notebookContextManager}
|
|
284
|
+
toolbarRenderer={this.cellToolbarFactory}
|
|
285
|
+
commandRegistry={this.commandRegistry}
|
|
286
|
+
menuRegistry={this.menuRegistry} />
|
|
287
|
+
</div>
|
|
270
288
|
</PerfectScrollbar>
|
|
271
289
|
</div>
|
|
272
290
|
</div>;
|
|
@@ -282,6 +300,12 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
282
300
|
this.notebookEditorService.removeNotebookEditor(this);
|
|
283
301
|
}
|
|
284
302
|
|
|
303
|
+
requestOuputPresentationChange(cellHandle: number, output?: NotebookCellOutputModel): void {
|
|
304
|
+
if (output) {
|
|
305
|
+
this.cellOutputWebview.requestOutputPresentationUpdate(cellHandle, output);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
285
309
|
postKernelMessage(message: unknown): void {
|
|
286
310
|
this.onDidPostKernelMessageEmitter.fire(message);
|
|
287
311
|
}
|
|
@@ -307,6 +331,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
307
331
|
}
|
|
308
332
|
|
|
309
333
|
override dispose(): void {
|
|
334
|
+
this.cellOutputWebview.dispose();
|
|
310
335
|
this.notebookContextManager.dispose();
|
|
311
336
|
this.onDidChangeModelEmitter.dispose();
|
|
312
337
|
this.onDidPostKernelMessageEmitter.dispose();
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
import '../../src/browser/style/index.css';
|
|
17
17
|
|
|
18
18
|
import { ContainerModule } from '@theia/core/shared/inversify';
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
FrontendApplicationContribution, KeybindingContribution, LabelProviderContribution, OpenHandler, UndoRedoHandler, WidgetFactory, WidgetStatusBarContribution
|
|
21
|
+
} from '@theia/core/lib/browser';
|
|
20
22
|
import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution';
|
|
21
23
|
import { NotebookOpenHandler } from './notebook-open-handler';
|
|
22
24
|
import { CommandContribution, MenuContribution, ResourceResolver, } from '@theia/core';
|
|
@@ -49,6 +51,7 @@ import { NotebookOptionsService } from './service/notebook-options';
|
|
|
49
51
|
import { NotebookUndoRedoHandler } from './contributions/notebook-undo-redo-handler';
|
|
50
52
|
import { NotebookStatusBarContribution } from './contributions/notebook-status-bar-contribution';
|
|
51
53
|
import { NotebookCellEditorService } from './service/notebook-cell-editor-service';
|
|
54
|
+
import { NotebookCellStatusBarService } from './service/notebook-cell-status-bar-service';
|
|
52
55
|
|
|
53
56
|
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
54
57
|
bind(NotebookColorContribution).toSelf().inSingletonScope();
|
|
@@ -72,6 +75,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
72
75
|
bind(NotebookKernelQuickPickService).toSelf().inSingletonScope();
|
|
73
76
|
bind(NotebookClipboardService).toSelf().inSingletonScope();
|
|
74
77
|
bind(NotebookCellEditorService).toSelf().inSingletonScope();
|
|
78
|
+
bind(NotebookCellStatusBarService).toSelf().inSingletonScope();
|
|
75
79
|
|
|
76
80
|
bind(NotebookCellResourceResolver).toSelf().inSingletonScope();
|
|
77
81
|
bind(ResourceResolver).toService(NotebookCellResourceResolver);
|
|
@@ -117,5 +121,5 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
117
121
|
bind(UndoRedoHandler).toService(NotebookUndoRedoHandler);
|
|
118
122
|
|
|
119
123
|
bind(NotebookStatusBarContribution).toSelf().inSingletonScope();
|
|
120
|
-
bind(
|
|
124
|
+
bind(WidgetStatusBarContribution).toService(NotebookStatusBarContribution);
|
|
121
125
|
});
|
|
@@ -14,20 +14,38 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { Disposable } from '@theia/core';
|
|
18
|
-
import { NotebookCellModel } from '../view-model/notebook-cell-model';
|
|
17
|
+
import { Disposable, Event } from '@theia/core';
|
|
19
18
|
import { NotebookModel } from '../view-model/notebook-model';
|
|
19
|
+
import { NotebookEditorWidget } from '../notebook-editor-widget';
|
|
20
|
+
import { NotebookContentChangedEvent } from '../notebook-types';
|
|
21
|
+
import { NotebookCellOutputModel } from '../view-model/notebook-cell-output-model';
|
|
22
|
+
import { NotebookCellModel } from '../view-model/notebook-cell-model';
|
|
20
23
|
|
|
21
24
|
export const CellOutputWebviewFactory = Symbol('outputWebviewFactory');
|
|
25
|
+
export const CellOutputWebview = Symbol('outputWebview');
|
|
22
26
|
|
|
23
|
-
export type CellOutputWebviewFactory = (
|
|
27
|
+
export type CellOutputWebviewFactory = () => Promise<CellOutputWebview>;
|
|
28
|
+
|
|
29
|
+
export interface OutputRenderEvent {
|
|
30
|
+
cellHandle: number;
|
|
31
|
+
outputId: string;
|
|
32
|
+
outputHeight: number;
|
|
33
|
+
}
|
|
24
34
|
|
|
25
35
|
export interface CellOutputWebview extends Disposable {
|
|
26
36
|
|
|
27
37
|
readonly id: string;
|
|
28
38
|
|
|
39
|
+
init(notebook: NotebookModel, editor: NotebookEditorWidget): void;
|
|
40
|
+
|
|
29
41
|
render(): React.ReactNode;
|
|
30
42
|
|
|
43
|
+
setCellHeight(cell: NotebookCellModel, height: number): void;
|
|
44
|
+
cellsChanged(cellEvent: NotebookContentChangedEvent[]): void;
|
|
45
|
+
onDidRenderOutput: Event<OutputRenderEvent>
|
|
46
|
+
|
|
47
|
+
requestOutputPresentationUpdate(cellHandle: number, output: NotebookCellOutputModel): void;
|
|
48
|
+
|
|
31
49
|
attachWebview(): void;
|
|
32
50
|
isAttached(): boolean
|
|
33
51
|
}
|
|
@@ -15,12 +15,17 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { Emitter, URI } from '@theia/core';
|
|
18
|
-
import { injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
19
19
|
import { SimpleMonacoEditor } from '@theia/monaco/lib/browser/simple-monaco-editor';
|
|
20
|
+
import { NotebookEditorWidgetService } from './notebook-editor-widget-service';
|
|
21
|
+
import { CellUri } from '../../common';
|
|
20
22
|
|
|
21
23
|
@injectable()
|
|
22
24
|
export class NotebookCellEditorService {
|
|
23
25
|
|
|
26
|
+
@inject(NotebookEditorWidgetService)
|
|
27
|
+
protected readonly notebookEditorWidgetService: NotebookEditorWidgetService;
|
|
28
|
+
|
|
24
29
|
protected onDidChangeCellEditorsEmitter = new Emitter<void>();
|
|
25
30
|
readonly onDidChangeCellEditors = this.onDidChangeCellEditorsEmitter.event;
|
|
26
31
|
|
|
@@ -31,6 +36,17 @@ export class NotebookCellEditorService {
|
|
|
31
36
|
|
|
32
37
|
protected currentCellEditors: Map<string, SimpleMonacoEditor> = new Map();
|
|
33
38
|
|
|
39
|
+
@postConstruct()
|
|
40
|
+
protected init(): void {
|
|
41
|
+
this.notebookEditorWidgetService.onDidChangeCurrentEditor(editor => {
|
|
42
|
+
// if defocus notebook editor or another notebook editor is focused, clear the active cell
|
|
43
|
+
if (!editor || (this.currentActiveCell && CellUri.parse(this.currentActiveCell.uri)?.notebook.toString() !== editor?.model?.uri.toString())) {
|
|
44
|
+
this.currentActiveCell = undefined;
|
|
45
|
+
this.onDidChangeFocusedCellEditorEmitter.fire(undefined);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
34
50
|
get allCellEditors(): SimpleMonacoEditor[] {
|
|
35
51
|
return Array.from(this.currentCellEditors.values());
|
|
36
52
|
}
|
|
@@ -46,8 +62,10 @@ export class NotebookCellEditorService {
|
|
|
46
62
|
}
|
|
47
63
|
|
|
48
64
|
editorFocusChanged(editor?: SimpleMonacoEditor): void {
|
|
49
|
-
|
|
50
|
-
|
|
65
|
+
if (editor) {
|
|
66
|
+
this.currentActiveCell = editor;
|
|
67
|
+
this.onDidChangeFocusedCellEditorEmitter.fire(editor);
|
|
68
|
+
}
|
|
51
69
|
}
|
|
52
70
|
|
|
53
71
|
getActiveCell(): SimpleMonacoEditor | undefined {
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2024 TypeFox and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
/*---------------------------------------------------------------------------------------------
|
|
17
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
18
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
19
|
+
*--------------------------------------------------------------------------------------------*/
|
|
20
|
+
|
|
21
|
+
import { CancellationToken, Command, Disposable, Emitter, Event, URI } from '@theia/core';
|
|
22
|
+
import { CellStatusbarAlignment } from '../../common';
|
|
23
|
+
import { ThemeColor } from '@theia/core/lib/common/theme';
|
|
24
|
+
import { AccessibilityInformation } from '@theia/core/lib/common/accessibility';
|
|
25
|
+
import { injectable } from '@theia/core/shared/inversify';
|
|
26
|
+
import { MarkdownString } from '@theia/core/lib/common/markdown-rendering';
|
|
27
|
+
|
|
28
|
+
export interface NotebookCellStatusBarItem {
|
|
29
|
+
readonly alignment: CellStatusbarAlignment;
|
|
30
|
+
readonly priority?: number;
|
|
31
|
+
readonly text: string;
|
|
32
|
+
readonly color?: string | ThemeColor;
|
|
33
|
+
readonly backgroundColor?: string | ThemeColor;
|
|
34
|
+
readonly tooltip?: string | MarkdownString;
|
|
35
|
+
readonly command?: string | (Command & { arguments?: unknown[] });
|
|
36
|
+
readonly accessibilityInformation?: AccessibilityInformation;
|
|
37
|
+
readonly opacity?: string;
|
|
38
|
+
readonly onlyShowWhenActive?: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface NotebookCellStatusBarItemList {
|
|
41
|
+
items: NotebookCellStatusBarItem[];
|
|
42
|
+
dispose?(): void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface NotebookCellStatusBarItemProvider {
|
|
46
|
+
viewType: string;
|
|
47
|
+
onDidChangeStatusBarItems?: Event<void>;
|
|
48
|
+
provideCellStatusBarItems(uri: URI, index: number, token: CancellationToken): Promise<NotebookCellStatusBarItemList | undefined>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@injectable()
|
|
52
|
+
export class NotebookCellStatusBarService implements Disposable {
|
|
53
|
+
|
|
54
|
+
protected readonly onDidChangeProvidersEmitter = new Emitter<void>();
|
|
55
|
+
readonly onDidChangeProviders: Event<void> = this.onDidChangeProvidersEmitter.event;
|
|
56
|
+
|
|
57
|
+
protected readonly onDidChangeItemsEmitter = new Emitter<void>();
|
|
58
|
+
readonly onDidChangeItems: Event<void> = this.onDidChangeItemsEmitter.event;
|
|
59
|
+
|
|
60
|
+
protected readonly providers: NotebookCellStatusBarItemProvider[] = [];
|
|
61
|
+
|
|
62
|
+
registerCellStatusBarItemProvider(provider: NotebookCellStatusBarItemProvider): Disposable {
|
|
63
|
+
this.providers.push(provider);
|
|
64
|
+
let changeListener: Disposable | undefined;
|
|
65
|
+
if (provider.onDidChangeStatusBarItems) {
|
|
66
|
+
changeListener = provider.onDidChangeStatusBarItems(() => this.onDidChangeItemsEmitter.fire());
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
this.onDidChangeProvidersEmitter.fire();
|
|
70
|
+
|
|
71
|
+
return Disposable.create(() => {
|
|
72
|
+
changeListener?.dispose();
|
|
73
|
+
const idx = this.providers.findIndex(p => p === provider);
|
|
74
|
+
this.providers.splice(idx, 1);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async getStatusBarItemsForCell(notebookUri: URI, cellIndex: number, viewType: string, token: CancellationToken): Promise<NotebookCellStatusBarItemList[]> {
|
|
79
|
+
const providers = this.providers.filter(p => p.viewType === viewType || p.viewType === '*');
|
|
80
|
+
return Promise.all(providers.map(async p => {
|
|
81
|
+
try {
|
|
82
|
+
return await p.provideCellStatusBarItems(notebookUri, cellIndex, token) ?? { items: [] };
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.error(e);
|
|
85
|
+
return { items: [] };
|
|
86
|
+
}
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
dispose(): void {
|
|
91
|
+
this.onDidChangeItemsEmitter.dispose();
|
|
92
|
+
this.onDidChangeProvidersEmitter.dispose();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -45,13 +45,23 @@ export class NotebookEditorWidgetService {
|
|
|
45
45
|
protected readonly onDidChangeFocusedEditorEmitter = new Emitter<NotebookEditorWidget | undefined>();
|
|
46
46
|
readonly onDidChangeFocusedEditor = this.onDidChangeFocusedEditorEmitter.event;
|
|
47
47
|
|
|
48
|
+
protected readonly onDidChangeCurrentEditorEmitter = new Emitter<NotebookEditorWidget | undefined>();
|
|
49
|
+
readonly onDidChangeCurrentEditor = this.onDidChangeCurrentEditorEmitter.event;
|
|
50
|
+
|
|
48
51
|
focusedEditor?: NotebookEditorWidget = undefined;
|
|
49
52
|
|
|
53
|
+
currentEditor?: NotebookEditorWidget = undefined;
|
|
54
|
+
|
|
50
55
|
@postConstruct()
|
|
51
56
|
protected init(): void {
|
|
52
57
|
this.applicationShell.onDidChangeActiveWidget(event => {
|
|
53
58
|
this.notebookEditorFocusChanged(event.newValue as NotebookEditorWidget, event.newValue instanceof NotebookEditorWidget);
|
|
54
59
|
});
|
|
60
|
+
this.applicationShell.onDidChangeCurrentWidget(event => {
|
|
61
|
+
if (event.newValue instanceof NotebookEditorWidget || event.oldValue instanceof NotebookEditorWidget) {
|
|
62
|
+
this.currentNotebookEditorChanged(event.newValue);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
55
65
|
}
|
|
56
66
|
|
|
57
67
|
// --- editor management
|
|
@@ -98,4 +108,14 @@ export class NotebookEditorWidgetService {
|
|
|
98
108
|
}
|
|
99
109
|
}
|
|
100
110
|
|
|
111
|
+
currentNotebookEditorChanged(newEditor: unknown): void {
|
|
112
|
+
if (newEditor instanceof NotebookEditorWidget) {
|
|
113
|
+
this.currentEditor = newEditor;
|
|
114
|
+
this.onDidChangeCurrentEditorEmitter.fire(newEditor);
|
|
115
|
+
} else if (this.currentEditor?.isDisposed || !this.currentEditor?.isVisible) {
|
|
116
|
+
this.currentEditor = undefined;
|
|
117
|
+
this.onDidChangeCurrentEditorEmitter.fire(undefined);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
101
121
|
}
|
|
@@ -20,10 +20,24 @@
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
.theia-notebook-cell-list {
|
|
23
|
+
position: absolute;
|
|
24
|
+
top: 0;
|
|
25
|
+
width: 100%;
|
|
23
26
|
overflow-y: auto;
|
|
24
27
|
list-style: none;
|
|
25
28
|
padding-left: 0px;
|
|
26
29
|
background-color: var(--theia-notebook-editorBackground);
|
|
30
|
+
z-index: 0;
|
|
31
|
+
pointer-events: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
.theia-notebook-cell-output-webview {
|
|
36
|
+
padding: 5px 0px;
|
|
37
|
+
margin: 0px 15px 0px 50px;
|
|
38
|
+
width: calc(100% - 60px);
|
|
39
|
+
position: absolute;
|
|
40
|
+
z-index: 0;
|
|
27
41
|
}
|
|
28
42
|
|
|
29
43
|
.theia-notebook-cell {
|
|
@@ -69,7 +83,8 @@
|
|
|
69
83
|
/* Rendered Markdown Content */
|
|
70
84
|
|
|
71
85
|
.theia-notebook-markdown-content {
|
|
72
|
-
|
|
86
|
+
pointer-events: all;
|
|
87
|
+
padding: 8px 16px 8px 0px;
|
|
73
88
|
font-size: var(--theia-notebook-markdown-size);
|
|
74
89
|
}
|
|
75
90
|
|
|
@@ -87,9 +102,13 @@
|
|
|
87
102
|
padding-bottom: 0;
|
|
88
103
|
}
|
|
89
104
|
|
|
105
|
+
.theia-notebook-markdown-sidebar {
|
|
106
|
+
width: 35px;
|
|
107
|
+
}
|
|
108
|
+
|
|
90
109
|
/* Markdown cell edit mode */
|
|
91
110
|
.theia-notebook-cell-content:has(.theia-notebook-markdown-editor-container>.theia-notebook-cell-editor) {
|
|
92
|
-
|
|
111
|
+
pointer-events: all;
|
|
93
112
|
margin-right: var(--theia-notebook-cell-editor-margin-right);
|
|
94
113
|
outline: 1px solid var(--theia-notebook-cellBorderColor);
|
|
95
114
|
}
|
|
@@ -108,6 +127,7 @@
|
|
|
108
127
|
}
|
|
109
128
|
|
|
110
129
|
.theia-notebook-cell-editor-container {
|
|
130
|
+
pointer-events: all;
|
|
111
131
|
width: calc(100% - 46px);
|
|
112
132
|
flex: 1;
|
|
113
133
|
outline: 1px solid var(--theia-notebook-cellBorderColor);
|
|
@@ -149,6 +169,7 @@
|
|
|
149
169
|
}
|
|
150
170
|
|
|
151
171
|
.theia-notebook-cell-toolbar {
|
|
172
|
+
pointer-events: all;
|
|
152
173
|
border: 1px solid var(--theia-notebook-cellToolbarSeparator);
|
|
153
174
|
display: flex;
|
|
154
175
|
position: absolute;
|
|
@@ -161,11 +182,15 @@
|
|
|
161
182
|
display: flex;
|
|
162
183
|
flex-direction: column;
|
|
163
184
|
padding: 2px;
|
|
164
|
-
background-color: var(--theia-editor-background);
|
|
165
185
|
flex-grow: 1;
|
|
166
186
|
}
|
|
167
187
|
|
|
168
188
|
.theia-notebook-cell-sidebar {
|
|
189
|
+
pointer-events: all;
|
|
190
|
+
display: flex;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.theia-notebook-cell-sidebar-actions {
|
|
169
194
|
display: flex;
|
|
170
195
|
flex-direction: column;
|
|
171
196
|
}
|
|
@@ -194,6 +219,7 @@
|
|
|
194
219
|
}
|
|
195
220
|
|
|
196
221
|
.theia-notebook-cell-divider {
|
|
222
|
+
pointer-events: all;
|
|
197
223
|
height: 25px;
|
|
198
224
|
width: 100%;
|
|
199
225
|
}
|
|
@@ -303,19 +329,19 @@
|
|
|
303
329
|
margin: 1px 0 0 4px;
|
|
304
330
|
}
|
|
305
331
|
|
|
306
|
-
.theia-notebook-cell-output-webview {
|
|
307
|
-
padding: 5px 0px;
|
|
308
|
-
margin: 0px 15px 0px 9px;
|
|
309
|
-
width: 100%;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
332
|
.theia-notebook-cell-drop-indicator {
|
|
313
333
|
height: 2px;
|
|
314
334
|
background-color: var(--theia-notebook-focusedCellBorder);
|
|
315
335
|
width: 100%;
|
|
316
336
|
}
|
|
317
337
|
|
|
338
|
+
.theia-notebook-collapsed-output-container {
|
|
339
|
+
width: 0;
|
|
340
|
+
overflow: visible;
|
|
341
|
+
}
|
|
342
|
+
|
|
318
343
|
.theia-notebook-collapsed-output {
|
|
344
|
+
text-wrap: nowrap;
|
|
319
345
|
padding: 4px 8px;
|
|
320
346
|
color: var(--theia-foreground);
|
|
321
347
|
margin-left: 30px;
|
|
@@ -482,3 +508,22 @@ mark.theia-find-match.theia-find-match-selected {
|
|
|
482
508
|
color: var(--theia-editor-findMatchForeground);
|
|
483
509
|
background-color: var(--theia-editor-findMatchBackground);
|
|
484
510
|
}
|
|
511
|
+
|
|
512
|
+
.cell-status-bar-item {
|
|
513
|
+
align-items: center;
|
|
514
|
+
display: flex;
|
|
515
|
+
height: 16px;
|
|
516
|
+
margin: 0 3px;
|
|
517
|
+
overflow: hidden;
|
|
518
|
+
padding: 0 3px;
|
|
519
|
+
text-overflow: clip;
|
|
520
|
+
white-space: pre;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.cell-status-item-has-command {
|
|
524
|
+
cursor: pointer;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
.cell-status-item-has-command:hover {
|
|
528
|
+
background-color: var(--theia-toolbar-hoverBackground);
|
|
529
|
+
}
|
|
@@ -103,15 +103,7 @@ export class CellEditor extends React.Component<CellEditorProps, {}> {
|
|
|
103
103
|
this.props.notebookContextManager.scopedStore.setContext(NOTEBOOK_CELL_CURSOR_LAST_LINE, currentLine === lineCount);
|
|
104
104
|
}));
|
|
105
105
|
|
|
106
|
-
this.toDispose.push(this.props.cell.onWillBlurCellEditor(() =>
|
|
107
|
-
let parent = this.container?.parentElement;
|
|
108
|
-
while (parent && !parent.classList.contains('theia-notebook-cell')) {
|
|
109
|
-
parent = parent.parentElement;
|
|
110
|
-
}
|
|
111
|
-
if (parent) {
|
|
112
|
-
parent.focus();
|
|
113
|
-
}
|
|
114
|
-
}));
|
|
106
|
+
this.toDispose.push(this.props.cell.onWillBlurCellEditor(() => this.blurEditor()));
|
|
115
107
|
|
|
116
108
|
this.toDispose.push(this.props.cell.onDidChangeEditorOptions(options => {
|
|
117
109
|
this.editor?.getControl().updateOptions(options);
|
|
@@ -130,7 +122,7 @@ export class CellEditor extends React.Component<CellEditorProps, {}> {
|
|
|
130
122
|
|
|
131
123
|
this.toDispose.push(this.props.notebookModel.onDidChangeSelectedCell(e => {
|
|
132
124
|
if (e.cell !== this.props.cell && this.editor?.getControl().hasTextFocus()) {
|
|
133
|
-
this.
|
|
125
|
+
this.blurEditor();
|
|
134
126
|
}
|
|
135
127
|
}));
|
|
136
128
|
if (!this.props.notebookViewportService || (this.container && this.props.notebookViewportService.isElementInViewport(this.container))) {
|
|
@@ -212,6 +204,11 @@ export class CellEditor extends React.Component<CellEditorProps, {}> {
|
|
|
212
204
|
|
|
213
205
|
this.toDispose.push(this.editor.getControl().onDidChangeCursorSelection(e => {
|
|
214
206
|
const selectedText = this.editor!.getControl().getModel()!.getValueInRange(e.selection);
|
|
207
|
+
// TODO handle secondary selections
|
|
208
|
+
this.props.cell.selection = {
|
|
209
|
+
start: { line: e.selection.startLineNumber - 1, character: e.selection.startColumn - 1 },
|
|
210
|
+
end: { line: e.selection.endLineNumber - 1, character: e.selection.endColumn - 1 }
|
|
211
|
+
};
|
|
215
212
|
this.props.notebookModel.selectedText = selectedText;
|
|
216
213
|
}));
|
|
217
214
|
this.toDispose.push(this.editor.getControl().onDidChangeCursorPosition(e => {
|
|
@@ -226,7 +223,7 @@ export class CellEditor extends React.Component<CellEditorProps, {}> {
|
|
|
226
223
|
}));
|
|
227
224
|
this.props.notebookCellEditorService.editorCreated(uri, this.editor);
|
|
228
225
|
this.setMatches();
|
|
229
|
-
if (
|
|
226
|
+
if (notebookModel.selectedCell === cell) {
|
|
230
227
|
this.editor.getControl().focus();
|
|
231
228
|
}
|
|
232
229
|
}
|
|
@@ -273,4 +270,14 @@ export class CellEditor extends React.Component<CellEditorProps, {}> {
|
|
|
273
270
|
</div >;
|
|
274
271
|
}
|
|
275
272
|
|
|
273
|
+
protected blurEditor(): void {
|
|
274
|
+
let parent = this.container?.parentElement;
|
|
275
|
+
while (parent && !parent.classList.contains('theia-notebook-cell')) {
|
|
276
|
+
parent = parent.parentElement;
|
|
277
|
+
}
|
|
278
|
+
if (parent) {
|
|
279
|
+
parent.focus();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
276
283
|
}
|