@theia/notebook 1.53.2 → 1.55.0-next.14
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-actions-contribution.d.ts.map +1 -1
- package/lib/browser/contributions/notebook-actions-contribution.js +5 -2
- package/lib/browser/contributions/notebook-actions-contribution.js.map +1 -1
- package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts.map +1 -1
- package/lib/browser/contributions/notebook-cell-actions-contribution.js +10 -6
- 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/index.d.ts +1 -0
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +1 -0
- package/lib/browser/index.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 +27 -4
- 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/notebook-open-handler.d.ts +3 -2
- package/lib/browser/notebook-open-handler.d.ts.map +1 -1
- package/lib/browser/notebook-open-handler.js +12 -5
- package/lib/browser/notebook-open-handler.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 +19 -0
- package/lib/browser/service/notebook-cell-editor-service.d.ts.map +1 -0
- package/lib/browser/service/notebook-cell-editor-service.js +77 -0
- package/lib/browser/service/notebook-cell-editor-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 +2 -0
- package/lib/browser/view/notebook-cell-editor.d.ts.map +1 -1
- package/lib/browser/view/notebook-cell-editor.js +12 -1
- 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-code-cell-view.d.ts +19 -9
- package/lib/browser/view/notebook-code-cell-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-code-cell-view.js +58 -70
- package/lib/browser/view/notebook-code-cell-view.js.map +1 -1
- package/lib/browser/view/notebook-markdown-cell-view.d.ts +3 -0
- package/lib/browser/view/notebook-markdown-cell-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-markdown-cell-view.js +17 -5
- package/lib/browser/view/notebook-markdown-cell-view.js.map +1 -1
- package/lib/browser/view-model/notebook-cell-model.d.ts +5 -0
- package/lib/browser/view-model/notebook-cell-model.d.ts.map +1 -1
- package/lib/browser/view-model/notebook-cell-model.js +10 -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-actions-contribution.ts +4 -1
- package/src/browser/contributions/notebook-cell-actions-contribution.ts +10 -7
- package/src/browser/contributions/notebook-status-bar-contribution.ts +23 -34
- package/src/browser/index.ts +1 -0
- package/src/browser/notebook-editor-widget.tsx +35 -10
- package/src/browser/notebook-frontend-module.ts +6 -2
- package/src/browser/notebook-open-handler.ts +13 -7
- package/src/browser/renderers/cell-output-webview.ts +21 -3
- package/src/browser/service/notebook-cell-editor-service.ts +74 -0
- package/src/browser/service/notebook-editor-widget-service.ts +20 -0
- package/src/browser/style/index.css +41 -10
- package/src/browser/view/notebook-cell-editor.tsx +18 -5
- package/src/browser/view/notebook-cell-list-view.tsx +44 -13
- package/src/browser/view/notebook-code-cell-view.tsx +82 -87
- package/src/browser/view/notebook-markdown-cell-view.tsx +19 -5
- package/src/browser/view-model/notebook-cell-model.ts +13 -0
- package/src/browser/view-model/notebook-cell-output-model.ts +0 -8
- package/src/browser/view-model/notebook-model.ts +5 -1
|
@@ -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(() => {
|
|
@@ -212,7 +227,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
212
227
|
|
|
213
228
|
protected override onActivateRequest(msg: Message): void {
|
|
214
229
|
super.onActivateRequest(msg);
|
|
215
|
-
this.node.focus();
|
|
230
|
+
(this.node.getElementsByClassName('theia-notebook-main-container')[0] as HTMLDivElement)?.focus();
|
|
216
231
|
}
|
|
217
232
|
|
|
218
233
|
getResourceUri(): URI | undefined {
|
|
@@ -233,7 +248,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
233
248
|
|
|
234
249
|
protected render(): ReactNode {
|
|
235
250
|
if (this._model) {
|
|
236
|
-
return <div className='theia-notebook-main-container'>
|
|
251
|
+
return <div className='theia-notebook-main-container' tabIndex={-1}>
|
|
237
252
|
<div className='theia-notebook-overlay'>
|
|
238
253
|
<NotebookFindWidget
|
|
239
254
|
ref={this._findWidgetRef}
|
|
@@ -261,17 +276,20 @@ 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>;
|
|
273
291
|
} else {
|
|
274
|
-
return <div className='theia-notebook-main-container'>
|
|
292
|
+
return <div className='theia-notebook-main-container' tabIndex={-1}>
|
|
275
293
|
<div className='theia-notebook-main-loading-indicator'></div>
|
|
276
294
|
</div>;
|
|
277
295
|
}
|
|
@@ -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';
|
|
@@ -48,6 +50,7 @@ import { bindNotebookPreferences } from './contributions/notebook-preferences';
|
|
|
48
50
|
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';
|
|
53
|
+
import { NotebookCellEditorService } from './service/notebook-cell-editor-service';
|
|
51
54
|
|
|
52
55
|
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
53
56
|
bind(NotebookColorContribution).toSelf().inSingletonScope();
|
|
@@ -70,6 +73,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
70
73
|
bind(NotebookKernelHistoryService).toSelf().inSingletonScope();
|
|
71
74
|
bind(NotebookKernelQuickPickService).toSelf().inSingletonScope();
|
|
72
75
|
bind(NotebookClipboardService).toSelf().inSingletonScope();
|
|
76
|
+
bind(NotebookCellEditorService).toSelf().inSingletonScope();
|
|
73
77
|
|
|
74
78
|
bind(NotebookCellResourceResolver).toSelf().inSingletonScope();
|
|
75
79
|
bind(ResourceResolver).toService(NotebookCellResourceResolver);
|
|
@@ -115,5 +119,5 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
115
119
|
bind(UndoRedoHandler).toService(NotebookUndoRedoHandler);
|
|
116
120
|
|
|
117
121
|
bind(NotebookStatusBarContribution).toSelf().inSingletonScope();
|
|
118
|
-
bind(
|
|
122
|
+
bind(WidgetStatusBarContribution).toService(NotebookStatusBarContribution);
|
|
119
123
|
});
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { URI, MaybePromise, Disposable } from '@theia/core';
|
|
18
|
-
import { NavigatableWidgetOpenHandler, WidgetOpenerOptions } from '@theia/core/lib/browser';
|
|
19
|
-
import { injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import { NavigatableWidgetOpenHandler, PreferenceService, WidgetOpenerOptions, getDefaultHandler, defaultHandlerPriority } from '@theia/core/lib/browser';
|
|
19
|
+
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
20
20
|
import { NotebookFileSelector, NotebookTypeDescriptor } from '../common/notebook-protocol';
|
|
21
21
|
import { NotebookEditorWidget } from './notebook-editor-widget';
|
|
22
22
|
import { match } from '@theia/core/lib/common/glob';
|
|
@@ -33,6 +33,9 @@ export class NotebookOpenHandler extends NavigatableWidgetOpenHandler<NotebookEd
|
|
|
33
33
|
|
|
34
34
|
protected notebookTypes: NotebookTypeDescriptor[] = [];
|
|
35
35
|
|
|
36
|
+
@inject(PreferenceService)
|
|
37
|
+
protected readonly preferenceService: PreferenceService;
|
|
38
|
+
|
|
36
39
|
registerNotebookType(notebookType: NotebookTypeDescriptor): Disposable {
|
|
37
40
|
this.notebookTypes.push(notebookType);
|
|
38
41
|
return Disposable.create(() => {
|
|
@@ -41,15 +44,16 @@ export class NotebookOpenHandler extends NavigatableWidgetOpenHandler<NotebookEd
|
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
canHandle(uri: URI, options?: NotebookWidgetOpenerOptions): MaybePromise<number> {
|
|
47
|
+
const defaultHandler = getDefaultHandler(uri, this.preferenceService);
|
|
44
48
|
if (options?.notebookType) {
|
|
45
|
-
return this.canHandleType(uri, this.notebookTypes.find(type => type.type === options.notebookType));
|
|
49
|
+
return this.canHandleType(uri, this.notebookTypes.find(type => type.type === options.notebookType), defaultHandler);
|
|
46
50
|
}
|
|
47
|
-
return Math.max(...this.notebookTypes.map(type => this.canHandleType(uri, type)));
|
|
51
|
+
return Math.max(...this.notebookTypes.map(type => this.canHandleType(uri, type), defaultHandler));
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
canHandleType(uri: URI, notebookType?: NotebookTypeDescriptor): number {
|
|
54
|
+
canHandleType(uri: URI, notebookType?: NotebookTypeDescriptor, defaultHandler?: string): number {
|
|
51
55
|
if (notebookType?.selector && this.matches(notebookType.selector, uri)) {
|
|
52
|
-
return this.calculatePriority(notebookType);
|
|
56
|
+
return notebookType.type === defaultHandler ? defaultHandlerPriority : this.calculatePriority(notebookType);
|
|
53
57
|
} else {
|
|
54
58
|
return 0;
|
|
55
59
|
}
|
|
@@ -93,7 +97,9 @@ export class NotebookOpenHandler extends NavigatableWidgetOpenHandler<NotebookEd
|
|
|
93
97
|
...widgetOptions
|
|
94
98
|
};
|
|
95
99
|
}
|
|
96
|
-
const
|
|
100
|
+
const defaultHandler = getDefaultHandler(uri, this.preferenceService);
|
|
101
|
+
const notebookType = this.notebookTypes.find(type => type.type === defaultHandler)
|
|
102
|
+
|| this.findHighestPriorityType(uri);
|
|
97
103
|
if (!notebookType) {
|
|
98
104
|
throw new Error('No notebook types registered for uri: ' + uri.toString());
|
|
99
105
|
}
|
|
@@ -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
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
import { Emitter, URI } from '@theia/core';
|
|
18
|
+
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
19
|
+
import { SimpleMonacoEditor } from '@theia/monaco/lib/browser/simple-monaco-editor';
|
|
20
|
+
import { NotebookEditorWidgetService } from './notebook-editor-widget-service';
|
|
21
|
+
import { CellUri } from '../../common';
|
|
22
|
+
|
|
23
|
+
@injectable()
|
|
24
|
+
export class NotebookCellEditorService {
|
|
25
|
+
|
|
26
|
+
@inject(NotebookEditorWidgetService)
|
|
27
|
+
protected readonly notebookEditorWidgetService: NotebookEditorWidgetService;
|
|
28
|
+
|
|
29
|
+
protected onDidChangeCellEditorsEmitter = new Emitter<void>();
|
|
30
|
+
readonly onDidChangeCellEditors = this.onDidChangeCellEditorsEmitter.event;
|
|
31
|
+
|
|
32
|
+
protected onDidChangeFocusedCellEditorEmitter = new Emitter<SimpleMonacoEditor | undefined>();
|
|
33
|
+
readonly onDidChangeFocusedCellEditor = this.onDidChangeFocusedCellEditorEmitter.event;
|
|
34
|
+
|
|
35
|
+
protected currentActiveCell?: SimpleMonacoEditor;
|
|
36
|
+
|
|
37
|
+
protected currentCellEditors: Map<string, SimpleMonacoEditor> = new Map();
|
|
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
|
+
|
|
50
|
+
get allCellEditors(): SimpleMonacoEditor[] {
|
|
51
|
+
return Array.from(this.currentCellEditors.values());
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
editorCreated(uri: URI, editor: SimpleMonacoEditor): void {
|
|
55
|
+
this.currentCellEditors.set(uri.toString(), editor);
|
|
56
|
+
this.onDidChangeCellEditorsEmitter.fire();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
editorDisposed(uri: URI): void {
|
|
60
|
+
this.currentCellEditors.delete(uri.toString());
|
|
61
|
+
this.onDidChangeCellEditorsEmitter.fire();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
editorFocusChanged(editor?: SimpleMonacoEditor): void {
|
|
65
|
+
if (editor) {
|
|
66
|
+
this.currentActiveCell = editor;
|
|
67
|
+
this.onDidChangeFocusedCellEditorEmitter.fire(editor);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getActiveCell(): SimpleMonacoEditor | undefined {
|
|
72
|
+
return this.currentActiveCell;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -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,13 +127,15 @@
|
|
|
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);
|
|
114
134
|
margin: 0px 16px 0px 10px;
|
|
115
135
|
}
|
|
116
136
|
|
|
117
|
-
|
|
137
|
+
/* Only mark an editor cell focused if the editor has focus */
|
|
138
|
+
.theia-notebook-cell-editor-container:has(.monaco-editor.focused) {
|
|
118
139
|
outline-color: var(--theia-notebook-focusedEditorBorder);
|
|
119
140
|
}
|
|
120
141
|
|
|
@@ -148,6 +169,7 @@
|
|
|
148
169
|
}
|
|
149
170
|
|
|
150
171
|
.theia-notebook-cell-toolbar {
|
|
172
|
+
pointer-events: all;
|
|
151
173
|
border: 1px solid var(--theia-notebook-cellToolbarSeparator);
|
|
152
174
|
display: flex;
|
|
153
175
|
position: absolute;
|
|
@@ -160,11 +182,15 @@
|
|
|
160
182
|
display: flex;
|
|
161
183
|
flex-direction: column;
|
|
162
184
|
padding: 2px;
|
|
163
|
-
background-color: var(--theia-editor-background);
|
|
164
185
|
flex-grow: 1;
|
|
165
186
|
}
|
|
166
187
|
|
|
167
188
|
.theia-notebook-cell-sidebar {
|
|
189
|
+
pointer-events: all;
|
|
190
|
+
display: flex;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.theia-notebook-cell-sidebar-actions {
|
|
168
194
|
display: flex;
|
|
169
195
|
flex-direction: column;
|
|
170
196
|
}
|
|
@@ -193,6 +219,7 @@
|
|
|
193
219
|
}
|
|
194
220
|
|
|
195
221
|
.theia-notebook-cell-divider {
|
|
222
|
+
pointer-events: all;
|
|
196
223
|
height: 25px;
|
|
197
224
|
width: 100%;
|
|
198
225
|
}
|
|
@@ -209,6 +236,10 @@
|
|
|
209
236
|
overflow: hidden;
|
|
210
237
|
}
|
|
211
238
|
|
|
239
|
+
.theia-notebook-main-container:focus {
|
|
240
|
+
outline: none;
|
|
241
|
+
}
|
|
242
|
+
|
|
212
243
|
.theia-notebook-main-container .theia-notebook-main-loading-indicator {
|
|
213
244
|
/* `progress-animation` is defined in `packages/core/src/browser/style/progress-bar.css` */
|
|
214
245
|
animation: progress-animation 1.8s 0s infinite cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
@@ -298,19 +329,19 @@
|
|
|
298
329
|
margin: 1px 0 0 4px;
|
|
299
330
|
}
|
|
300
331
|
|
|
301
|
-
.theia-notebook-cell-output-webview {
|
|
302
|
-
padding: 5px 0px;
|
|
303
|
-
margin: 0px 15px 0px 9px;
|
|
304
|
-
width: 100%;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
332
|
.theia-notebook-cell-drop-indicator {
|
|
308
333
|
height: 2px;
|
|
309
334
|
background-color: var(--theia-notebook-focusedCellBorder);
|
|
310
335
|
width: 100%;
|
|
311
336
|
}
|
|
312
337
|
|
|
338
|
+
.theia-notebook-collapsed-output-container {
|
|
339
|
+
width: 0;
|
|
340
|
+
overflow: visible;
|
|
341
|
+
}
|
|
342
|
+
|
|
313
343
|
.theia-notebook-collapsed-output {
|
|
344
|
+
text-wrap: nowrap;
|
|
314
345
|
padding: 4px 8px;
|
|
315
346
|
color: var(--theia-foreground);
|
|
316
347
|
margin-left: 30px;
|
|
@@ -30,13 +30,15 @@ import { EditorExtensionsRegistry } from '@theia/monaco-editor-core/esm/vs/edito
|
|
|
30
30
|
import { ModelDecorationOptions } from '@theia/monaco-editor-core/esm/vs/editor/common/model/textModel';
|
|
31
31
|
import { IModelDeltaDecoration, OverviewRulerLane, TrackedRangeStickiness } from '@theia/monaco-editor-core/esm/vs/editor/common/model';
|
|
32
32
|
import { animationFrame } from '@theia/core/lib/browser';
|
|
33
|
+
import { NotebookCellEditorService } from '../service/notebook-cell-editor-service';
|
|
33
34
|
|
|
34
35
|
interface CellEditorProps {
|
|
35
|
-
notebookModel: NotebookModel
|
|
36
|
-
cell: NotebookCellModel
|
|
37
|
-
monacoServices: MonacoEditorServices
|
|
36
|
+
notebookModel: NotebookModel;
|
|
37
|
+
cell: NotebookCellModel;
|
|
38
|
+
monacoServices: MonacoEditorServices;
|
|
38
39
|
notebookContextManager: NotebookContextManager;
|
|
39
|
-
|
|
40
|
+
notebookCellEditorService: NotebookCellEditorService;
|
|
41
|
+
notebookViewportService?: NotebookViewportService;
|
|
40
42
|
fontInfo?: BareFontInfo;
|
|
41
43
|
}
|
|
42
44
|
|
|
@@ -153,6 +155,9 @@ export class CellEditor extends React.Component<CellEditorProps, {}> {
|
|
|
153
155
|
}
|
|
154
156
|
|
|
155
157
|
protected disposeEditor(): void {
|
|
158
|
+
if (this.editor) {
|
|
159
|
+
this.props.notebookCellEditorService.editorDisposed(this.editor.uri);
|
|
160
|
+
}
|
|
156
161
|
this.toDispose.dispose();
|
|
157
162
|
this.toDispose = new DisposableCollection();
|
|
158
163
|
}
|
|
@@ -197,7 +202,14 @@ export class CellEditor extends React.Component<CellEditorProps, {}> {
|
|
|
197
202
|
}));
|
|
198
203
|
this.toDispose.push(this.editor.getControl().onDidFocusEditorText(() => {
|
|
199
204
|
this.props.notebookModel.setSelectedCell(cell, false);
|
|
205
|
+
this.props.notebookCellEditorService.editorFocusChanged(this.editor);
|
|
206
|
+
}));
|
|
207
|
+
this.toDispose.push(this.editor.getControl().onDidBlurEditorText(() => {
|
|
208
|
+
if (this.props.notebookCellEditorService.getActiveCell()?.uri.toString() === this.props.cell.uri.toString()) {
|
|
209
|
+
this.props.notebookCellEditorService.editorFocusChanged(undefined);
|
|
210
|
+
}
|
|
200
211
|
}));
|
|
212
|
+
|
|
201
213
|
this.toDispose.push(this.editor.getControl().onDidChangeCursorSelection(e => {
|
|
202
214
|
const selectedText = this.editor!.getControl().getModel()!.getValueInRange(e.selection);
|
|
203
215
|
this.props.notebookModel.selectedText = selectedText;
|
|
@@ -212,10 +224,11 @@ export class CellEditor extends React.Component<CellEditorProps, {}> {
|
|
|
212
224
|
this.props.notebookContextManager.scopedStore.setContext(NOTEBOOK_CELL_CURSOR_LAST_LINE, false);
|
|
213
225
|
}
|
|
214
226
|
}));
|
|
227
|
+
this.props.notebookCellEditorService.editorCreated(uri, this.editor);
|
|
228
|
+
this.setMatches();
|
|
215
229
|
if (cell.editing && notebookModel.selectedCell === cell) {
|
|
216
230
|
this.editor.getControl().focus();
|
|
217
231
|
}
|
|
218
|
-
this.setMatches();
|
|
219
232
|
}
|
|
220
233
|
}
|
|
221
234
|
|