@theia/notebook 1.41.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/README.md +30 -0
- package/lib/browser/contributions/notebook-actions-contribution.d.ts +27 -0
- package/lib/browser/contributions/notebook-actions-contribution.d.ts.map +1 -0
- package/lib/browser/contributions/notebook-actions-contribution.js +172 -0
- package/lib/browser/contributions/notebook-actions-contribution.js.map +1 -0
- package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts +30 -0
- package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts.map +1 -0
- package/lib/browser/contributions/notebook-cell-actions-contribution.js +200 -0
- package/lib/browser/contributions/notebook-cell-actions-contribution.js.map +1 -0
- package/lib/browser/contributions/notebook-color-contribution.d.ts +6 -0
- package/lib/browser/contributions/notebook-color-contribution.d.ts.map +1 -0
- package/lib/browser/contributions/notebook-color-contribution.js +252 -0
- package/lib/browser/contributions/notebook-color-contribution.js.map +1 -0
- package/lib/browser/contributions/notebook-context-keys.d.ts +38 -0
- package/lib/browser/contributions/notebook-context-keys.d.ts.map +1 -0
- package/lib/browser/contributions/notebook-context-keys.js +95 -0
- package/lib/browser/contributions/notebook-context-keys.js.map +1 -0
- package/lib/browser/index.d.ts +11 -0
- package/lib/browser/index.d.ts.map +1 -0
- package/lib/browser/index.js +38 -0
- package/lib/browser/index.js.map +1 -0
- package/lib/browser/notebook-cell-resource-resolver.d.ts +20 -0
- package/lib/browser/notebook-cell-resource-resolver.d.ts.map +1 -0
- package/lib/browser/notebook-cell-resource-resolver.js +75 -0
- package/lib/browser/notebook-cell-resource-resolver.js.map +1 -0
- package/lib/browser/notebook-editor-widget-factory.d.ts +17 -0
- package/lib/browser/notebook-editor-widget-factory.d.ts.map +1 -0
- package/lib/browser/notebook-editor-widget-factory.js +78 -0
- package/lib/browser/notebook-editor-widget-factory.js.map +1 -0
- package/lib/browser/notebook-editor-widget.d.ts +49 -0
- package/lib/browser/notebook-editor-widget.d.ts.map +1 -0
- package/lib/browser/notebook-editor-widget.js +150 -0
- package/lib/browser/notebook-editor-widget.js.map +1 -0
- package/lib/browser/notebook-frontend-module.d.ts +5 -0
- package/lib/browser/notebook-frontend-module.d.ts.map +1 -0
- package/lib/browser/notebook-frontend-module.js +81 -0
- package/lib/browser/notebook-frontend-module.js.map +1 -0
- package/lib/browser/notebook-open-handler.d.ts +18 -0
- package/lib/browser/notebook-open-handler.d.ts.map +1 -0
- package/lib/browser/notebook-open-handler.js +94 -0
- package/lib/browser/notebook-open-handler.js.map +1 -0
- package/lib/browser/notebook-renderer-registry.d.ts +17 -0
- package/lib/browser/notebook-renderer-registry.d.ts.map +1 -0
- package/lib/browser/notebook-renderer-registry.js +63 -0
- package/lib/browser/notebook-renderer-registry.js.map +1 -0
- package/lib/browser/notebook-type-registry.d.ts +7 -0
- package/lib/browser/notebook-type-registry.d.ts.map +1 -0
- package/lib/browser/notebook-type-registry.js +42 -0
- package/lib/browser/notebook-type-registry.js.map +1 -0
- package/lib/browser/renderers/cell-output-webview.d.ts +12 -0
- package/lib/browser/renderers/cell-output-webview.d.ts.map +1 -0
- package/lib/browser/renderers/cell-output-webview.js +20 -0
- package/lib/browser/renderers/cell-output-webview.js.map +1 -0
- package/lib/browser/service/notebook-cell-context-manager.d.ts +16 -0
- package/lib/browser/service/notebook-cell-context-manager.d.ts.map +1 -0
- package/lib/browser/service/notebook-cell-context-manager.js +83 -0
- package/lib/browser/service/notebook-cell-context-manager.js.map +1 -0
- package/lib/browser/service/notebook-editor-service.d.ts +22 -0
- package/lib/browser/service/notebook-editor-service.d.ts.map +1 -0
- package/lib/browser/service/notebook-editor-service.js +95 -0
- package/lib/browser/service/notebook-editor-service.js.map +1 -0
- package/lib/browser/service/notebook-execution-service.d.ts +25 -0
- package/lib/browser/service/notebook-execution-service.d.ts.map +1 -0
- package/lib/browser/service/notebook-execution-service.js +140 -0
- package/lib/browser/service/notebook-execution-service.js.map +1 -0
- package/lib/browser/service/notebook-execution-state-service.d.ts +94 -0
- package/lib/browser/service/notebook-execution-state-service.d.ts.map +1 -0
- package/lib/browser/service/notebook-execution-state-service.js +250 -0
- package/lib/browser/service/notebook-execution-state-service.js.map +1 -0
- package/lib/browser/service/notebook-kernel-history-service.d.ts +23 -0
- package/lib/browser/service/notebook-kernel-history-service.d.ts.map +1 -0
- package/lib/browser/service/notebook-kernel-history-service.js +109 -0
- package/lib/browser/service/notebook-kernel-history-service.js.map +1 -0
- package/lib/browser/service/notebook-kernel-quick-pick-service.d.ts +65 -0
- package/lib/browser/service/notebook-kernel-quick-pick-service.d.ts.map +1 -0
- package/lib/browser/service/notebook-kernel-quick-pick-service.js +430 -0
- package/lib/browser/service/notebook-kernel-quick-pick-service.js.map +1 -0
- package/lib/browser/service/notebook-kernel-service.d.ts +112 -0
- package/lib/browser/service/notebook-kernel-service.d.ts.map +1 -0
- package/lib/browser/service/notebook-kernel-service.js +274 -0
- package/lib/browser/service/notebook-kernel-service.js.map +1 -0
- package/lib/browser/service/notebook-model-resolver-service.d.ts +26 -0
- package/lib/browser/service/notebook-model-resolver-service.d.ts.map +1 -0
- package/lib/browser/service/notebook-model-resolver-service.js +139 -0
- package/lib/browser/service/notebook-model-resolver-service.js.map +1 -0
- package/lib/browser/service/notebook-renderer-messaging-service.d.ts +30 -0
- package/lib/browser/service/notebook-renderer-messaging-service.d.ts.map +1 -0
- package/lib/browser/service/notebook-renderer-messaging-service.js +94 -0
- package/lib/browser/service/notebook-renderer-messaging-service.js.map +1 -0
- package/lib/browser/service/notebook-service.d.ts +64 -0
- package/lib/browser/service/notebook-service.d.ts.map +1 -0
- package/lib/browser/service/notebook-service.js +162 -0
- package/lib/browser/service/notebook-service.js.map +1 -0
- package/lib/browser/view/notebook-cell-editor.d.ts +26 -0
- package/lib/browser/view/notebook-cell-editor.d.ts.map +1 -0
- package/lib/browser/view/notebook-cell-editor.js +79 -0
- package/lib/browser/view/notebook-cell-editor.js.map +1 -0
- package/lib/browser/view/notebook-cell-list-view.d.ts +43 -0
- package/lib/browser/view/notebook-cell-list-view.d.ts.map +1 -0
- package/lib/browser/view/notebook-cell-list-view.js +111 -0
- package/lib/browser/view/notebook-cell-list-view.js.map +1 -0
- package/lib/browser/view/notebook-cell-toolbar-factory.d.ts +25 -0
- package/lib/browser/view/notebook-cell-toolbar-factory.d.ts.map +1 -0
- package/lib/browser/view/notebook-cell-toolbar-factory.js +93 -0
- package/lib/browser/view/notebook-cell-toolbar-factory.js.map +1 -0
- package/lib/browser/view/notebook-cell-toolbar.d.ts +25 -0
- package/lib/browser/view/notebook-cell-toolbar.d.ts.map +1 -0
- package/lib/browser/view/notebook-cell-toolbar.js +50 -0
- package/lib/browser/view/notebook-cell-toolbar.js.map +1 -0
- package/lib/browser/view/notebook-code-cell-view.d.ts +47 -0
- package/lib/browser/view/notebook-code-cell-view.d.ts.map +1 -0
- package/lib/browser/view/notebook-code-cell-view.js +166 -0
- package/lib/browser/view/notebook-code-cell-view.js.map +1 -0
- package/lib/browser/view/notebook-main-toolbar.d.ts +31 -0
- package/lib/browser/view/notebook-main-toolbar.d.ts.map +1 -0
- package/lib/browser/view/notebook-main-toolbar.js +118 -0
- package/lib/browser/view/notebook-main-toolbar.js.map +1 -0
- package/lib/browser/view/notebook-markdown-cell-view.d.ts +12 -0
- package/lib/browser/view/notebook-markdown-cell-view.d.ts.map +1 -0
- package/lib/browser/view/notebook-markdown-cell-view.js +70 -0
- package/lib/browser/view/notebook-markdown-cell-view.js.map +1 -0
- package/lib/browser/view-model/notebook-cell-model.d.ts +74 -0
- package/lib/browser/view-model/notebook-cell-model.d.ts.map +1 -0
- package/lib/browser/view-model/notebook-cell-model.js +226 -0
- package/lib/browser/view-model/notebook-cell-model.js.map +1 -0
- package/lib/browser/view-model/notebook-cell-output-model.d.ts +19 -0
- package/lib/browser/view-model/notebook-cell-output-model.d.ts.map +1 -0
- package/lib/browser/view-model/notebook-cell-output-model.js +61 -0
- package/lib/browser/view-model/notebook-cell-output-model.js.map +1 -0
- package/lib/browser/view-model/notebook-model.d.ts +59 -0
- package/lib/browser/view-model/notebook-model.d.ts.map +1 -0
- package/lib/browser/view-model/notebook-model.js +315 -0
- package/lib/browser/view-model/notebook-model.js.map +1 -0
- package/lib/common/index.d.ts +3 -0
- package/lib/common/index.d.ts.map +1 -0
- package/lib/common/index.js +30 -0
- package/lib/common/index.js.map +1 -0
- package/lib/common/notebook-common.d.ts +344 -0
- package/lib/common/notebook-common.d.ts.map +1 -0
- package/lib/common/notebook-common.js +112 -0
- package/lib/common/notebook-common.js.map +1 -0
- package/lib/common/notebook-protocol.d.ts +21 -0
- package/lib/common/notebook-protocol.d.ts.map +1 -0
- package/lib/common/notebook-protocol.js +18 -0
- package/lib/common/notebook-protocol.js.map +1 -0
- package/lib/common/notebook-range.d.ts +14 -0
- package/lib/common/notebook-range.d.ts.map +1 -0
- package/lib/common/notebook-range.js +18 -0
- package/lib/common/notebook-range.js.map +1 -0
- package/package.json +52 -0
- package/src/browser/contributions/notebook-actions-contribution.ts +171 -0
- package/src/browser/contributions/notebook-cell-actions-contribution.ts +204 -0
- package/src/browser/contributions/notebook-color-contribution.ts +268 -0
- package/src/browser/contributions/notebook-context-keys.ts +99 -0
- package/src/browser/index.ts +26 -0
- package/src/browser/notebook-cell-resource-resolver.ts +79 -0
- package/src/browser/notebook-editor-widget-factory.ts +70 -0
- package/src/browser/notebook-editor-widget.tsx +157 -0
- package/src/browser/notebook-frontend-module.ts +95 -0
- package/src/browser/notebook-open-handler.ts +87 -0
- package/src/browser/notebook-renderer-registry.ts +62 -0
- package/src/browser/notebook-type-registry.ts +30 -0
- package/src/browser/renderers/cell-output-webview.ts +32 -0
- package/src/browser/service/notebook-cell-context-manager.ts +70 -0
- package/src/browser/service/notebook-editor-service.ts +86 -0
- package/src/browser/service/notebook-execution-service.ts +139 -0
- package/src/browser/service/notebook-execution-state-service.ts +322 -0
- package/src/browser/service/notebook-kernel-history-service.ts +109 -0
- package/src/browser/service/notebook-kernel-quick-pick-service.ts +494 -0
- package/src/browser/service/notebook-kernel-service.ts +357 -0
- package/src/browser/service/notebook-model-resolver-service.ts +141 -0
- package/src/browser/service/notebook-renderer-messaging-service.ts +111 -0
- package/src/browser/service/notebook-service.ts +178 -0
- package/src/browser/style/index.css +236 -0
- package/src/browser/view/notebook-cell-editor.tsx +97 -0
- package/src/browser/view/notebook-cell-list-view.tsx +171 -0
- package/src/browser/view/notebook-cell-toolbar-factory.tsx +91 -0
- package/src/browser/view/notebook-cell-toolbar.tsx +70 -0
- package/src/browser/view/notebook-code-cell-view.tsx +190 -0
- package/src/browser/view/notebook-main-toolbar.tsx +115 -0
- package/src/browser/view/notebook-markdown-cell-view.tsx +73 -0
- package/src/browser/view-model/notebook-cell-model.ts +271 -0
- package/src/browser/view-model/notebook-cell-output-model.ts +69 -0
- package/src/browser/view-model/notebook-model.ts +372 -0
- package/src/common/index.ts +18 -0
- package/src/common/notebook-common.ts +462 -0
- package/src/common/notebook-protocol.ts +35 -0
- package/src/common/notebook-range.ts +30 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2023 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 { Disposable, DisposableCollection, Emitter, URI } from '@theia/core';
|
|
18
|
+
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
19
|
+
import { BinaryBuffer } from '@theia/core/lib/common/buffer';
|
|
20
|
+
import { NotebookData, NotebookExtensionDescription, TransientOptions } from '../../common';
|
|
21
|
+
import { NotebookModel, NotebookModelFactory, NotebookModelProps } from '../view-model/notebook-model';
|
|
22
|
+
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
|
23
|
+
import { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
|
|
24
|
+
import { NotebookCellModel, NotebookCellModelFactory, NotebookCellModelProps } from '../view-model/notebook-cell-model';
|
|
25
|
+
import { Deferred } from '@theia/core/lib/common/promise-util';
|
|
26
|
+
|
|
27
|
+
export const NotebookProvider = Symbol('notebook provider');
|
|
28
|
+
|
|
29
|
+
export interface SimpleNotebookProviderInfo {
|
|
30
|
+
readonly notebookType: string,
|
|
31
|
+
readonly serializer: NotebookSerializer,
|
|
32
|
+
readonly extensionData: NotebookExtensionDescription
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface NotebookSerializer {
|
|
36
|
+
options: TransientOptions;
|
|
37
|
+
dataToNotebook(data: BinaryBuffer): Promise<NotebookData>;
|
|
38
|
+
notebookToData(data: NotebookData): Promise<BinaryBuffer>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@injectable()
|
|
42
|
+
export class NotebookService implements Disposable {
|
|
43
|
+
|
|
44
|
+
@inject(FileService)
|
|
45
|
+
protected fileService: FileService;
|
|
46
|
+
|
|
47
|
+
@inject(MonacoTextModelService)
|
|
48
|
+
protected modelService: MonacoTextModelService;
|
|
49
|
+
|
|
50
|
+
@inject(NotebookModelFactory)
|
|
51
|
+
protected notebookModelFactory: (props: NotebookModelProps) => NotebookModel;
|
|
52
|
+
|
|
53
|
+
@inject(NotebookCellModelFactory)
|
|
54
|
+
protected notebookCellModelFactory: (props: NotebookCellModelProps) => NotebookCellModel;
|
|
55
|
+
|
|
56
|
+
protected notebookSerializerEmitter = new Emitter<string>();
|
|
57
|
+
readonly onNotebookSerializer = this.notebookSerializerEmitter.event;
|
|
58
|
+
|
|
59
|
+
protected readonly disposables = new DisposableCollection();
|
|
60
|
+
|
|
61
|
+
protected readonly notebookProviders = new Map<string, SimpleNotebookProviderInfo>();
|
|
62
|
+
protected readonly notebookModels = new Map<string, NotebookModel>();
|
|
63
|
+
|
|
64
|
+
protected readonly didAddViewTypeEmitter = new Emitter<string>();
|
|
65
|
+
readonly onDidAddViewType = this.didAddViewTypeEmitter.event;
|
|
66
|
+
|
|
67
|
+
protected readonly didRemoveViewTypeEmitter = new Emitter<string>();
|
|
68
|
+
readonly onDidRemoveViewType = this.didRemoveViewTypeEmitter.event;
|
|
69
|
+
|
|
70
|
+
protected readonly willOpenNotebookTypeEmitter = new Emitter<string>();
|
|
71
|
+
readonly onWillOpenNotebook = this.willOpenNotebookTypeEmitter.event;
|
|
72
|
+
|
|
73
|
+
protected readonly willAddNotebookDocumentEmitter = new Emitter<URI>();
|
|
74
|
+
readonly onWillAddNotebookDocument = this.willAddNotebookDocumentEmitter.event;
|
|
75
|
+
protected readonly didAddNotebookDocumentEmitter = new Emitter<NotebookModel>();
|
|
76
|
+
readonly onDidAddNotebookDocument = this.didAddNotebookDocumentEmitter.event;
|
|
77
|
+
protected readonly willRemoveNotebookDocumentEmitter = new Emitter<NotebookModel>();
|
|
78
|
+
readonly onWillRemoveNotebookDocument = this.willRemoveNotebookDocumentEmitter.event;
|
|
79
|
+
protected readonly didRemoveNotebookDocumentEmitter = new Emitter<NotebookModel>();
|
|
80
|
+
readonly onDidRemoveNotebookDocument = this.didRemoveNotebookDocumentEmitter.event;
|
|
81
|
+
|
|
82
|
+
dispose(): void {
|
|
83
|
+
this.disposables.dispose();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
protected readonly ready = new Deferred();
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Marks the notebook service as ready. From this point on, the service will start dispatching the `onNotebookSerializer` event.
|
|
90
|
+
*/
|
|
91
|
+
markReady(): void {
|
|
92
|
+
this.ready.resolve();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
registerNotebookSerializer(notebookType: string, extensionData: NotebookExtensionDescription, serializer: NotebookSerializer): Disposable {
|
|
96
|
+
if (this.notebookProviders.has(notebookType)) {
|
|
97
|
+
throw new Error(`notebook provider for viewtype '${notebookType}' already exists`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this.notebookProviders.set(notebookType, { notebookType: notebookType, serializer, extensionData });
|
|
101
|
+
this.didAddViewTypeEmitter.fire(notebookType);
|
|
102
|
+
|
|
103
|
+
return Disposable.create(() => {
|
|
104
|
+
this.notebookProviders.delete(notebookType);
|
|
105
|
+
this.didRemoveViewTypeEmitter.fire(notebookType);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async createNotebookModel(data: NotebookData, viewType: string, uri: URI): Promise<NotebookModel> {
|
|
110
|
+
const serializer = this.notebookProviders.get(viewType)?.serializer;
|
|
111
|
+
if (!serializer) {
|
|
112
|
+
throw new Error('no notebook serializer for ' + viewType);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this.willAddNotebookDocumentEmitter.fire(uri);
|
|
116
|
+
const model = this.notebookModelFactory({ data, uri, viewType, serializer });
|
|
117
|
+
this.notebookModels.set(uri.toString(), model);
|
|
118
|
+
// Resolve cell text models right after creating the notebook model
|
|
119
|
+
// This ensures that all text models are available in the plugin host
|
|
120
|
+
await Promise.all(model.cells.map(e => e.resolveTextModel()));
|
|
121
|
+
this.didAddNotebookDocumentEmitter.fire(model);
|
|
122
|
+
return model;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async getNotebookDataProvider(viewType: string): Promise<SimpleNotebookProviderInfo> {
|
|
126
|
+
await this.ready.promise;
|
|
127
|
+
await this.notebookSerializerEmitter.sequence(async listener => listener(`onNotebookSerializer:${viewType}`));
|
|
128
|
+
|
|
129
|
+
const result = await this.waitForNotebookProvider(viewType);
|
|
130
|
+
if (!result) {
|
|
131
|
+
throw new Error(`No provider registered for view type: '${viewType}'`);
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* When the application starts up, notebook providers from plugins are not registered yet.
|
|
138
|
+
* It takes a few seconds for the plugin host to start so that notebook data providers can be registered.
|
|
139
|
+
* This methods waits until the notebook provider is registered.
|
|
140
|
+
*/
|
|
141
|
+
protected async waitForNotebookProvider(type: string): Promise<SimpleNotebookProviderInfo | undefined> {
|
|
142
|
+
if (this.notebookProviders.has(type)) {
|
|
143
|
+
return this.notebookProviders.get(type);
|
|
144
|
+
}
|
|
145
|
+
const deferred = new Deferred<SimpleNotebookProviderInfo | undefined>();
|
|
146
|
+
// 20 seconds of timeout
|
|
147
|
+
const timeoutDuration = 20_000;
|
|
148
|
+
const disposable = this.onDidAddViewType(viewType => {
|
|
149
|
+
if (viewType === type) {
|
|
150
|
+
clearTimeout(timeout);
|
|
151
|
+
disposable.dispose();
|
|
152
|
+
deferred.resolve(this.notebookProviders.get(type));
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
const timeout = setTimeout(() => {
|
|
156
|
+
clearTimeout(timeout);
|
|
157
|
+
disposable.dispose();
|
|
158
|
+
deferred.reject();
|
|
159
|
+
}, timeoutDuration);
|
|
160
|
+
return deferred.promise;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
getNotebookEditorModel(uri: URI): NotebookModel | undefined {
|
|
164
|
+
return this.notebookModels.get(uri.toString());
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
getNotebookModels(): Iterable<NotebookModel> {
|
|
168
|
+
return this.notebookModels.values();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async willOpenNotebook(type: string): Promise<void> {
|
|
172
|
+
return this.willOpenNotebookTypeEmitter.sequence(async listener => listener(type));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
listNotebookDocuments(): NotebookModel[] {
|
|
176
|
+
return [...this.notebookModels.values()];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (C) 2023 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
|
+
:root {
|
|
18
|
+
--theia-notebook-markdown-size: 17px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.theia-notebook-cell-list {
|
|
22
|
+
overflow-y: auto;
|
|
23
|
+
list-style: none;
|
|
24
|
+
padding-left: 0px;
|
|
25
|
+
background-color: var(--theia-notebook-editorBackground);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.theia-notebook-cell {
|
|
29
|
+
cursor: grab;
|
|
30
|
+
display: flex;
|
|
31
|
+
margin: 10px 0px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.theia-notebook-cell:hover .theia-notebook-cell-marker {
|
|
35
|
+
visibility: visible;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.theia-notebook-cell-marker {
|
|
39
|
+
background-color: var(--theia-notebook-inactiveFocusedCellBorder);
|
|
40
|
+
width: 3px;
|
|
41
|
+
margin: 0px 8px 0px 4px;
|
|
42
|
+
border-radius: 4px;
|
|
43
|
+
visibility: hidden;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.theia-notebook-cell-marker-selected {
|
|
47
|
+
visibility: visible;
|
|
48
|
+
background-color: var(--theia-notebook-focusedCellBorder);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.theia-notebook-cell-marker:hover {
|
|
52
|
+
width: 5px;
|
|
53
|
+
margin: 0px 6px 0px 4px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.theia-notebook-cell-content {
|
|
57
|
+
flex: 1;
|
|
58
|
+
width: calc(100% - 15px);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.theia-notebook-markdown-content {
|
|
62
|
+
padding: 8px 16px 8px 36px;
|
|
63
|
+
font-size: var(--theia-notebook-markdown-size);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.theia-notebook-markdown-content > *:first-child {
|
|
67
|
+
margin-top: 0;
|
|
68
|
+
padding-top: 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.theia-notebook-markdown-content > *:only-child,
|
|
72
|
+
.theia-notebook-markdown-content > *:last-child {
|
|
73
|
+
margin-bottom: 0;
|
|
74
|
+
padding-bottom: 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.theia-notebook-empty-markdown {
|
|
78
|
+
opacity: 0.6;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.theia-notebook-cell-editor {
|
|
82
|
+
padding: 10px 10px 0 10px;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.theia-notebook-cell-editor-container {
|
|
86
|
+
width: calc(100% - 46px);
|
|
87
|
+
flex: 1;
|
|
88
|
+
outline: 1px solid var(--theia-notebook-cellBorderColor);
|
|
89
|
+
margin: 0px 10px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.theia-notebook-cell.focused .theia-notebook-cell-editor-container {
|
|
93
|
+
outline-color: var(--theia-notebook-focusedEditorBorder);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.notebook-cell-status {
|
|
97
|
+
display: flex;
|
|
98
|
+
flex-direction: row;
|
|
99
|
+
font-size: 12px;
|
|
100
|
+
height: 16px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.notebook-cell-status-left {
|
|
104
|
+
display: flex;
|
|
105
|
+
flex-direction: row;
|
|
106
|
+
flex-grow: 1;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.notebook-cell-status-right {
|
|
110
|
+
margin: 0 5px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.notebook-cell-status-item {
|
|
114
|
+
margin: 0 3px;
|
|
115
|
+
padding: 0 3px;
|
|
116
|
+
display: flex;
|
|
117
|
+
align-items: center;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.theia-notebook-cell-toolbar {
|
|
121
|
+
border: 1px solid var(--theia-notebook-cellToolbarSeparator);
|
|
122
|
+
display: flex;
|
|
123
|
+
position: absolute;
|
|
124
|
+
margin: -20px 0 0 66px;
|
|
125
|
+
padding: 2px;
|
|
126
|
+
background-color: var(--theia-editor-background);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.theia-notebook-cell-sidebar {
|
|
130
|
+
display: flex;
|
|
131
|
+
flex-direction: column;
|
|
132
|
+
padding: 2px;
|
|
133
|
+
background-color: var(--theia-editor-background);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.theia-notebook-cell-toolbar-item {
|
|
137
|
+
height: 18px;
|
|
138
|
+
width: 18px;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.theia-notebook-cell-toolbar-item:hover {
|
|
142
|
+
background-color: var(--theia-toolbar-hoverBackground);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.theia-notebook-cell-toolbar-item:active {
|
|
146
|
+
background-color: var(--theia-toolbar-active);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.theia-notebook-cell-divider {
|
|
150
|
+
height: 20px;
|
|
151
|
+
width: 100%;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.theia-notebook-cell-with-sidebar {
|
|
155
|
+
display: flex;
|
|
156
|
+
flex-direction: row;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.theia-notebook-cell-sidebar {
|
|
160
|
+
display: flex;
|
|
161
|
+
flex-direction: column;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.theia-notebook-main-toolbar {
|
|
165
|
+
position: sticky;
|
|
166
|
+
top: 0;
|
|
167
|
+
background: var(--theia-editor-background);
|
|
168
|
+
display: flex;
|
|
169
|
+
flex-direction: row;
|
|
170
|
+
z-index: 1;
|
|
171
|
+
/*needed to be on rendered on top of monaco editors*/
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.theia-notebook-main-toolbar-item {
|
|
175
|
+
height: 22px;
|
|
176
|
+
display: flex;
|
|
177
|
+
align-items: center;
|
|
178
|
+
margin: 0 4px;
|
|
179
|
+
padding: 2px;
|
|
180
|
+
text-align: center;
|
|
181
|
+
color: var(--theia-foreground) !important;
|
|
182
|
+
cursor: pointer;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.theia-notebook-main-toolbar-item:hover {
|
|
186
|
+
background-color: var(--theia-toolbar-hoverBackground);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.theia-notebook-main-toolbar-item-text {
|
|
190
|
+
padding: 0 4px;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.theia-notebook-toolbar-separator {
|
|
194
|
+
width: 1px;
|
|
195
|
+
background-color: var(--theia-notebook-cellToolbarSeparator);
|
|
196
|
+
margin: 0 4px;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.theia-notebook-add-cell-buttons {
|
|
200
|
+
justify-content: center;
|
|
201
|
+
display: flex;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.theia-notebook-add-cell-button {
|
|
205
|
+
border: 1px solid var(--theia-notebook-cellToolbarSeparator);
|
|
206
|
+
background-color: var(--theia-editor-background);
|
|
207
|
+
color: var(--theia-foreground);
|
|
208
|
+
vertical-align: middle;
|
|
209
|
+
text-align: center;
|
|
210
|
+
height: 24px;
|
|
211
|
+
margin: 0 8px;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.theia-notebook-add-cell-button:hover {
|
|
215
|
+
background-color: var(--theia-toolbar-hoverBackground);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.theia-notebook-add-cell-button:active {
|
|
219
|
+
background-color: var(--theia-toolbar-active);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.theia-notebook-add-cell-button-icon {
|
|
223
|
+
vertical-align: middle;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.theia-notebook-cell-output-webview {
|
|
227
|
+
padding: 5px 0px;
|
|
228
|
+
margin: 0px 10px;
|
|
229
|
+
width: 100%;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.theia-notebook-cell-drop-indicator {
|
|
233
|
+
height: 2px;
|
|
234
|
+
background-color: var(--theia-notebook-focusedCellBorder);
|
|
235
|
+
width: 100%;
|
|
236
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2023 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 * as React from '@theia/core/shared/react';
|
|
18
|
+
import { NotebookModel } from '../view-model/notebook-model';
|
|
19
|
+
import { NotebookCellModel } from '../view-model/notebook-cell-model';
|
|
20
|
+
import { MonacoCodeEditor } from '@theia/monaco/lib/browser/monaco-code-editor';
|
|
21
|
+
import { MonacoEditorServices } from '@theia/monaco/lib/browser/monaco-editor';
|
|
22
|
+
import { MonacoEditorProvider } from '@theia/monaco/lib/browser/monaco-editor-provider';
|
|
23
|
+
import { DisposableCollection } from '@theia/core';
|
|
24
|
+
|
|
25
|
+
interface CellEditorProps {
|
|
26
|
+
notebookModel: NotebookModel,
|
|
27
|
+
cell: NotebookCellModel,
|
|
28
|
+
monacoServices: MonacoEditorServices
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const DEFAULT_EDITOR_OPTIONS = {
|
|
32
|
+
...MonacoEditorProvider.inlineOptions,
|
|
33
|
+
minHeight: -1,
|
|
34
|
+
maxHeight: -1,
|
|
35
|
+
scrollbar: {
|
|
36
|
+
...MonacoEditorProvider.inlineOptions.scrollbar,
|
|
37
|
+
alwaysConsumeMouseWheel: false
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export class CellEditor extends React.Component<CellEditorProps, {}> {
|
|
42
|
+
|
|
43
|
+
protected editor?: MonacoCodeEditor;
|
|
44
|
+
protected toDispose = new DisposableCollection();
|
|
45
|
+
protected container?: HTMLDivElement;
|
|
46
|
+
|
|
47
|
+
override componentDidMount(): void {
|
|
48
|
+
this.disposeEditor();
|
|
49
|
+
this.initEditor();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
override componentWillUnmount(): void {
|
|
53
|
+
this.disposeEditor();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
protected disposeEditor(): void {
|
|
57
|
+
this.toDispose.dispose();
|
|
58
|
+
this.toDispose = new DisposableCollection();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
protected async initEditor(): Promise<void> {
|
|
62
|
+
const { cell, notebookModel, monacoServices } = this.props;
|
|
63
|
+
if (this.container) {
|
|
64
|
+
const editorNode = this.container;
|
|
65
|
+
const editorModel = await cell.resolveTextModel();
|
|
66
|
+
const uri = cell.uri;
|
|
67
|
+
this.editor = new MonacoCodeEditor(uri,
|
|
68
|
+
editorModel,
|
|
69
|
+
editorNode,
|
|
70
|
+
monacoServices,
|
|
71
|
+
DEFAULT_EDITOR_OPTIONS);
|
|
72
|
+
this.toDispose.push(this.editor);
|
|
73
|
+
this.editor.setLanguage(cell.language);
|
|
74
|
+
this.toDispose.push(this.editor.getControl().onDidContentSizeChange(() => {
|
|
75
|
+
editorNode.style.height = this.editor!.getControl().getContentHeight() + 7 + 'px';
|
|
76
|
+
this.editor!.setSize({ width: -1, height: this.editor!.getControl().getContentHeight() });
|
|
77
|
+
}));
|
|
78
|
+
this.toDispose.push(this.editor.onDocumentContentChanged(e => {
|
|
79
|
+
notebookModel.cellDirtyChanged(cell, true);
|
|
80
|
+
cell.source = e.document.getText();
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
protected assignRef = (component: HTMLDivElement) => {
|
|
86
|
+
this.container = component;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
protected handleResize = () => {
|
|
90
|
+
this.editor?.refresh();
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
override render(): React.ReactNode {
|
|
94
|
+
return <div className='theia-notebook-cell-editor' onResize={this.handleResize} id={this.props.cell.uri.toString()} ref={this.assignRef}></div>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2023 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
|
+
import * as React from '@theia/core/shared/react';
|
|
17
|
+
import { CellEditType, CellKind } from '../../common';
|
|
18
|
+
import { NotebookCellModel } from '../view-model/notebook-cell-model';
|
|
19
|
+
import { NotebookModel } from '../view-model/notebook-model';
|
|
20
|
+
import { NotebookCellToolbarFactory } from './notebook-cell-toolbar-factory';
|
|
21
|
+
import { codicon } from '@theia/core/lib/browser';
|
|
22
|
+
import { CommandRegistry, DisposableCollection, nls } from '@theia/core';
|
|
23
|
+
import { NotebookCommands } from '../contributions/notebook-actions-contribution';
|
|
24
|
+
import { NotebookCellActionContribution } from '../contributions/notebook-cell-actions-contribution';
|
|
25
|
+
|
|
26
|
+
export interface CellRenderer {
|
|
27
|
+
render(notebookData: NotebookModel, cell: NotebookCellModel, index: number): React.ReactNode
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface CellListProps {
|
|
31
|
+
renderers: Map<CellKind, CellRenderer>;
|
|
32
|
+
notebookModel: NotebookModel;
|
|
33
|
+
toolbarRenderer: NotebookCellToolbarFactory;
|
|
34
|
+
commandRegistry: CommandRegistry
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface NotebookCellListState {
|
|
38
|
+
selectedCell?: NotebookCellModel;
|
|
39
|
+
dragOverIndicator: { cell: NotebookCellModel, position: 'top' | 'bottom' } | undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class NotebookCellListView extends React.Component<CellListProps, NotebookCellListState> {
|
|
43
|
+
|
|
44
|
+
protected toDispose = new DisposableCollection();
|
|
45
|
+
|
|
46
|
+
constructor(props: CellListProps) {
|
|
47
|
+
super(props);
|
|
48
|
+
this.state = { selectedCell: undefined, dragOverIndicator: undefined };
|
|
49
|
+
this.toDispose.push(props.notebookModel.onDidAddOrRemoveCell(e => {
|
|
50
|
+
this.setState({ selectedCell: undefined });
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
override componentWillUnmount(): void {
|
|
55
|
+
this.toDispose.dispose();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
override render(): React.ReactNode {
|
|
59
|
+
return <ul className='theia-notebook-cell-list'>
|
|
60
|
+
{this.props.notebookModel.cells
|
|
61
|
+
.map((cell, index) =>
|
|
62
|
+
<React.Fragment key={'cell-' + cell.handle}>
|
|
63
|
+
<NotebookCellDivider onAddNewCell={(kind: CellKind) => this.onAddNewCell(kind, index)}
|
|
64
|
+
onDrop={e => this.onDrop(e, index)}
|
|
65
|
+
onDragOver={e => this.onDragOver(e, cell, 'top')} />
|
|
66
|
+
{this.shouldRenderDragOverIndicator(cell, 'top') && <CellDropIndicator />}
|
|
67
|
+
<li className={'theia-notebook-cell' + (this.state.selectedCell === cell ? ' focused' : '')}
|
|
68
|
+
onClick={() => {
|
|
69
|
+
this.setState({ selectedCell: cell });
|
|
70
|
+
this.props.notebookModel.setSelectedCell(cell);
|
|
71
|
+
}}
|
|
72
|
+
onDragStart={e => this.onDragStart(e, index)}
|
|
73
|
+
onDragOver={e => this.onDragOver(e, cell)}
|
|
74
|
+
onDrop={e => this.onDrop(e, index)}
|
|
75
|
+
draggable={true}
|
|
76
|
+
ref={(node: HTMLLIElement) => cell.refChanged(node)}>
|
|
77
|
+
<div className={'theia-notebook-cell-marker' + (this.state.selectedCell === cell ? ' theia-notebook-cell-marker-selected' : '')}></div>
|
|
78
|
+
<div className='theia-notebook-cell-content'>
|
|
79
|
+
{this.renderCellContent(cell, index)}
|
|
80
|
+
</div>
|
|
81
|
+
{this.state.selectedCell === cell &&
|
|
82
|
+
this.props.toolbarRenderer.renderCellToolbar(NotebookCellActionContribution.ACTION_MENU, this.props.notebookModel, cell)}
|
|
83
|
+
</li>
|
|
84
|
+
{this.shouldRenderDragOverIndicator(cell, 'bottom') && <CellDropIndicator />}
|
|
85
|
+
</React.Fragment>
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
<NotebookCellDivider onAddNewCell={(kind: CellKind) => this.onAddNewCell(kind, this.props.notebookModel.cells.length)}
|
|
89
|
+
onDrop={e => this.onDrop(e, this.props.notebookModel.cells.length - 1)}
|
|
90
|
+
onDragOver={e => this.onDragOver(e, this.props.notebookModel.cells[this.props.notebookModel.cells.length - 1], 'bottom')} />
|
|
91
|
+
</ul>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
renderCellContent(cell: NotebookCellModel, index: number): React.ReactNode {
|
|
95
|
+
const renderer = this.props.renderers.get(cell.cellKind);
|
|
96
|
+
if (!renderer) {
|
|
97
|
+
throw new Error(`No renderer found for cell type ${cell.cellKind}`);
|
|
98
|
+
}
|
|
99
|
+
return renderer.render(this.props.notebookModel, cell, index);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
protected onDragStart(event: React.DragEvent<HTMLLIElement>, index: number): void {
|
|
103
|
+
event.stopPropagation();
|
|
104
|
+
event.dataTransfer.setData('text/notebook-cell-index', index.toString());
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
protected onDragOver(event: React.DragEvent<HTMLLIElement>, cell: NotebookCellModel, position?: 'top' | 'bottom'): void {
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
event.stopPropagation();
|
|
110
|
+
// show indicator
|
|
111
|
+
this.setState({ ...this.state, dragOverIndicator: { cell, position: position ?? event.nativeEvent.offsetY < event.currentTarget.clientHeight / 2 ? 'top' : 'bottom' } });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
protected onDrop(event: React.DragEvent<HTMLLIElement>, dropElementIndex: number): void {
|
|
115
|
+
const index = parseInt(event.dataTransfer.getData('text/notebook-cell-index'));
|
|
116
|
+
const isTargetBelow = index < dropElementIndex;
|
|
117
|
+
let newIdx = this.state.dragOverIndicator?.position === 'top' ? dropElementIndex : dropElementIndex + 1;
|
|
118
|
+
newIdx = isTargetBelow ? newIdx - 1 : newIdx;
|
|
119
|
+
if (index !== undefined && index !== dropElementIndex) {
|
|
120
|
+
this.props.notebookModel.applyEdits([{
|
|
121
|
+
editType: CellEditType.Move,
|
|
122
|
+
length: 1,
|
|
123
|
+
index,
|
|
124
|
+
newIdx
|
|
125
|
+
}], true);
|
|
126
|
+
}
|
|
127
|
+
this.setState({ ...this.state, dragOverIndicator: undefined });
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
protected onAddNewCell(kind: CellKind, index: number): void {
|
|
131
|
+
this.props.commandRegistry.executeCommand(NotebookCommands.ADD_NEW_CELL_COMMAND.id,
|
|
132
|
+
this.props.notebookModel,
|
|
133
|
+
kind,
|
|
134
|
+
index
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
protected shouldRenderDragOverIndicator(cell: NotebookCellModel, position: 'top' | 'bottom'): boolean {
|
|
139
|
+
return this.state.dragOverIndicator !== undefined &&
|
|
140
|
+
this.state.dragOverIndicator.cell === cell &&
|
|
141
|
+
this.state.dragOverIndicator.position === position;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface NotebookCellDividerProps {
|
|
147
|
+
onAddNewCell: (type: CellKind) => void;
|
|
148
|
+
onDrop: (event: React.DragEvent<HTMLLIElement>) => void;
|
|
149
|
+
onDragOver: (event: React.DragEvent<HTMLLIElement>) => void;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function NotebookCellDivider({ onAddNewCell, onDrop, onDragOver }: NotebookCellDividerProps): React.JSX.Element {
|
|
153
|
+
const [hover, setHover] = React.useState(false);
|
|
154
|
+
|
|
155
|
+
return <li className='theia-notebook-cell-divider' onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)} onDrop={onDrop} onDragOver={onDragOver}>
|
|
156
|
+
{hover && <div className='theia-notebook-add-cell-buttons'>
|
|
157
|
+
<button className='theia-notebook-add-cell-button' onClick={() => onAddNewCell(CellKind.Code)} title={nls.localizeByDefault('Add Code Cell')}>
|
|
158
|
+
<div className={codicon('add') + ' theia-notebook-add-cell-button-icon'} />
|
|
159
|
+
{nls.localizeByDefault('Code')}
|
|
160
|
+
</button>
|
|
161
|
+
<button className='theia-notebook-add-cell-button' onClick={() => onAddNewCell(CellKind.Markup)} title={nls.localizeByDefault('Add Markdown Cell')}>
|
|
162
|
+
<div className={codicon('add') + ' theia-notebook-add-cell-button-icon'} />
|
|
163
|
+
{nls.localizeByDefault('Markdown')}
|
|
164
|
+
</button>
|
|
165
|
+
</div>}
|
|
166
|
+
</li>;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function CellDropIndicator(): React.JSX.Element {
|
|
170
|
+
return <div className='theia-notebook-cell-drop-indicator' />;
|
|
171
|
+
}
|