@theia/notebook 1.55.0-next.14 → 1.55.0-next.25
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 +49 -8
- package/lib/browser/contributions/notebook-cell-actions-contribution.js.map +1 -1
- package/lib/browser/notebook-frontend-module.d.ts.map +1 -1
- package/lib/browser/notebook-frontend-module.js +2 -0
- package/lib/browser/notebook-frontend-module.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/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-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 +13 -3
- package/lib/browser/view/notebook-code-cell-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-code-cell-view.js +47 -2
- 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 +4 -0
- package/lib/browser/view/notebook-markdown-cell-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-markdown-cell-view.js +13 -3
- package/lib/browser/view/notebook-markdown-cell-view.js.map +1 -1
- package/lib/browser/view-model/notebook-cell-model.d.ts +7 -0
- package/lib/browser/view-model/notebook-cell-model.d.ts.map +1 -1
- package/lib/browser/view-model/notebook-cell-model.js +11 -2
- package/lib/browser/view-model/notebook-cell-model.js.map +1 -1
- package/package.json +7 -7
- package/src/browser/contributions/notebook-cell-actions-contribution.ts +56 -9
- package/src/browser/notebook-frontend-module.ts +2 -0
- package/src/browser/service/notebook-cell-status-bar-service.ts +94 -0
- package/src/browser/style/index.css +19 -0
- package/src/browser/view/notebook-cell-editor.tsx +18 -11
- package/src/browser/view/notebook-cell-toolbar.tsx +1 -1
- package/src/browser/view/notebook-code-cell-view.tsx +65 -4
- package/src/browser/view/notebook-main-toolbar.tsx +4 -4
- package/src/browser/view/notebook-markdown-cell-view.tsx +20 -3
- package/src/browser/view-model/notebook-cell-model.ts +18 -2
|
@@ -51,6 +51,7 @@ import { NotebookOptionsService } from './service/notebook-options';
|
|
|
51
51
|
import { NotebookUndoRedoHandler } from './contributions/notebook-undo-redo-handler';
|
|
52
52
|
import { NotebookStatusBarContribution } from './contributions/notebook-status-bar-contribution';
|
|
53
53
|
import { NotebookCellEditorService } from './service/notebook-cell-editor-service';
|
|
54
|
+
import { NotebookCellStatusBarService } from './service/notebook-cell-status-bar-service';
|
|
54
55
|
|
|
55
56
|
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
56
57
|
bind(NotebookColorContribution).toSelf().inSingletonScope();
|
|
@@ -74,6 +75,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
74
75
|
bind(NotebookKernelQuickPickService).toSelf().inSingletonScope();
|
|
75
76
|
bind(NotebookClipboardService).toSelf().inSingletonScope();
|
|
76
77
|
bind(NotebookCellEditorService).toSelf().inSingletonScope();
|
|
78
|
+
bind(NotebookCellStatusBarService).toSelf().inSingletonScope();
|
|
77
79
|
|
|
78
80
|
bind(NotebookCellResourceResolver).toSelf().inSingletonScope();
|
|
79
81
|
bind(ResourceResolver).toService(NotebookCellResourceResolver);
|
|
@@ -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
|
+
}
|
|
@@ -508,3 +508,22 @@ mark.theia-find-match.theia-find-match-selected {
|
|
|
508
508
|
color: var(--theia-editor-findMatchForeground);
|
|
509
509
|
background-color: var(--theia-editor-findMatchBackground);
|
|
510
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
|
}
|
|
@@ -48,7 +48,7 @@ abstract class NotebookCellActionBar extends React.Component<NotebookCellToolbar
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
protected renderItem(item: NotebookCellToolbarItem): React.ReactNode {
|
|
51
|
-
return <div key={item.id} title={item.label} onClick={item.onClick} className={`${item.icon} ${ACTION_ITEM} theia-notebook-cell-toolbar-item`} />;
|
|
51
|
+
return <div key={item.id} id={item.id} title={item.label} onClick={item.onClick} className={`${item.icon} ${ACTION_ITEM} theia-notebook-cell-toolbar-item`} />;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
}
|
|
@@ -27,7 +27,7 @@ import { NotebookCellActionContribution, NotebookCellCommands } from '../contrib
|
|
|
27
27
|
import { CellExecution, NotebookExecutionStateService } from '../service/notebook-execution-state-service';
|
|
28
28
|
import { codicon } from '@theia/core/lib/browser';
|
|
29
29
|
import { NotebookCellExecutionState } from '../../common';
|
|
30
|
-
import { CommandRegistry, DisposableCollection, nls } from '@theia/core';
|
|
30
|
+
import { CancellationToken, CommandRegistry, DisposableCollection, nls } from '@theia/core';
|
|
31
31
|
import { NotebookContextManager } from '../service/notebook-context-manager';
|
|
32
32
|
import { NotebookViewportService } from './notebook-viewport-service';
|
|
33
33
|
import { EditorPreferences } from '@theia/editor/lib/browser';
|
|
@@ -36,6 +36,8 @@ import { MarkdownRenderer } from '@theia/core/lib/browser/markdown-rendering/mar
|
|
|
36
36
|
import { MarkdownString } from '@theia/monaco-editor-core/esm/vs/base/common/htmlContent';
|
|
37
37
|
import { NotebookCellEditorService } from '../service/notebook-cell-editor-service';
|
|
38
38
|
import { CellOutputWebview } from '../renderers/cell-output-webview';
|
|
39
|
+
import { NotebookCellStatusBarItem, NotebookCellStatusBarItemList, NotebookCellStatusBarService } from '../service/notebook-cell-status-bar-service';
|
|
40
|
+
import { LabelParser } from '@theia/core/lib/browser/label-parser';
|
|
39
41
|
|
|
40
42
|
@injectable()
|
|
41
43
|
export class NotebookCodeCellRenderer implements CellRenderer {
|
|
@@ -75,6 +77,12 @@ export class NotebookCodeCellRenderer implements CellRenderer {
|
|
|
75
77
|
@inject(CellOutputWebview)
|
|
76
78
|
protected readonly outputWebview: CellOutputWebview;
|
|
77
79
|
|
|
80
|
+
@inject(NotebookCellStatusBarService)
|
|
81
|
+
protected readonly notebookCellStatusBarService: NotebookCellStatusBarService;
|
|
82
|
+
|
|
83
|
+
@inject(LabelParser)
|
|
84
|
+
protected readonly labelParser: LabelParser;
|
|
85
|
+
|
|
78
86
|
render(notebookModel: NotebookModel, cell: NotebookCellModel, handle: number): React.ReactNode {
|
|
79
87
|
return <div className='theia-notebook-cell-with-sidebar' ref={ref => observeCellHeight(ref, cell)}>
|
|
80
88
|
<div className='theia-notebook-cell-editor-container'>
|
|
@@ -87,6 +95,8 @@ export class NotebookCodeCellRenderer implements CellRenderer {
|
|
|
87
95
|
<NotebookCodeCellStatus cell={cell} notebook={notebookModel}
|
|
88
96
|
commandRegistry={this.commandRegistry}
|
|
89
97
|
executionStateService={this.executionStateService}
|
|
98
|
+
cellStatusBarService={this.notebookCellStatusBarService}
|
|
99
|
+
labelParser={this.labelParser}
|
|
90
100
|
onClick={() => cell.requestFocusEditor()} />
|
|
91
101
|
</div >
|
|
92
102
|
</div >;
|
|
@@ -182,7 +192,9 @@ export interface NotebookCodeCellStatusProps {
|
|
|
182
192
|
notebook: NotebookModel;
|
|
183
193
|
cell: NotebookCellModel;
|
|
184
194
|
commandRegistry: CommandRegistry;
|
|
195
|
+
cellStatusBarService: NotebookCellStatusBarService;
|
|
185
196
|
executionStateService?: NotebookExecutionStateService;
|
|
197
|
+
labelParser: LabelParser;
|
|
186
198
|
onClick: () => void;
|
|
187
199
|
}
|
|
188
200
|
|
|
@@ -195,6 +207,8 @@ export class NotebookCodeCellStatus extends React.Component<NotebookCodeCellStat
|
|
|
195
207
|
|
|
196
208
|
protected toDispose = new DisposableCollection();
|
|
197
209
|
|
|
210
|
+
protected statusBarItems: NotebookCellStatusBarItemList[] = [];
|
|
211
|
+
|
|
198
212
|
constructor(props: NotebookCodeCellStatusProps) {
|
|
199
213
|
super(props);
|
|
200
214
|
|
|
@@ -225,6 +239,19 @@ export class NotebookCodeCellStatus extends React.Component<NotebookCodeCellStat
|
|
|
225
239
|
this.toDispose.push(props.cell.onDidChangeLanguage(() => {
|
|
226
240
|
this.forceUpdate();
|
|
227
241
|
}));
|
|
242
|
+
|
|
243
|
+
this.updateStatusBarItems();
|
|
244
|
+
this.props.cellStatusBarService.onDidChangeItems(() => this.updateStatusBarItems());
|
|
245
|
+
this.props.notebook.onContentChanged(() => this.updateStatusBarItems());
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async updateStatusBarItems(): Promise<void> {
|
|
249
|
+
this.statusBarItems = await this.props.cellStatusBarService.getStatusBarItemsForCell(
|
|
250
|
+
this.props.notebook.uri,
|
|
251
|
+
this.props.notebook.cells.indexOf(this.props.cell),
|
|
252
|
+
this.props.notebook.viewType,
|
|
253
|
+
CancellationToken.None);
|
|
254
|
+
this.forceUpdate();
|
|
228
255
|
}
|
|
229
256
|
|
|
230
257
|
override componentWillUnmount(): void {
|
|
@@ -235,6 +262,7 @@ export class NotebookCodeCellStatus extends React.Component<NotebookCodeCellStat
|
|
|
235
262
|
return <div className='notebook-cell-status' onClick={() => this.props.onClick()}>
|
|
236
263
|
<div className='notebook-cell-status-left'>
|
|
237
264
|
{this.props.executionStateService && this.renderExecutionState()}
|
|
265
|
+
{this.statusBarItems?.length && this.renderStatusBarItems()}
|
|
238
266
|
</div>
|
|
239
267
|
<div className='notebook-cell-status-right'>
|
|
240
268
|
<span className='notebook-cell-language-label' onClick={() => {
|
|
@@ -244,7 +272,7 @@ export class NotebookCodeCellStatus extends React.Component<NotebookCodeCellStat
|
|
|
244
272
|
</div>;
|
|
245
273
|
}
|
|
246
274
|
|
|
247
|
-
|
|
275
|
+
protected renderExecutionState(): React.ReactNode {
|
|
248
276
|
const state = this.state.currentExecution?.state;
|
|
249
277
|
const { lastRunSuccess } = this.props.cell.internalMetadata;
|
|
250
278
|
|
|
@@ -270,7 +298,7 @@ export class NotebookCodeCellStatus extends React.Component<NotebookCodeCellStat
|
|
|
270
298
|
</>;
|
|
271
299
|
}
|
|
272
300
|
|
|
273
|
-
|
|
301
|
+
protected getExecutionTime(): number {
|
|
274
302
|
const { runStartTime, runEndTime } = this.props.cell.internalMetadata;
|
|
275
303
|
const { executionTime } = this.state;
|
|
276
304
|
if (runStartTime !== undefined && runEndTime !== undefined) {
|
|
@@ -279,9 +307,42 @@ export class NotebookCodeCellStatus extends React.Component<NotebookCodeCellStat
|
|
|
279
307
|
return executionTime;
|
|
280
308
|
}
|
|
281
309
|
|
|
282
|
-
|
|
310
|
+
protected renderTime(ms: number): string {
|
|
283
311
|
return `${(ms / 1000).toLocaleString(undefined, { maximumFractionDigits: 1, minimumFractionDigits: 1 })}s`;
|
|
284
312
|
}
|
|
313
|
+
|
|
314
|
+
protected renderStatusBarItems(): React.ReactNode {
|
|
315
|
+
return <>
|
|
316
|
+
{
|
|
317
|
+
this.statusBarItems.flatMap((itemList, listIndex) =>
|
|
318
|
+
itemList.items.map((item, index) => this.renderStatusBarItem(item, `${listIndex}-${index}`)
|
|
319
|
+
)
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
</>;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
protected renderStatusBarItem(item: NotebookCellStatusBarItem, key: string): React.ReactNode {
|
|
326
|
+
const content = this.props.labelParser.parse(item.text).map(part => {
|
|
327
|
+
if (typeof part === 'string') {
|
|
328
|
+
return part;
|
|
329
|
+
} else {
|
|
330
|
+
return <span key={part.name} className={`codicon codicon-${part.name}`}></span>;
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
return <div key={key} className={`cell-status-bar-item ${item.command ? 'cell-status-item-has-command' : ''}`} onClick={async () => {
|
|
334
|
+
if (item.command) {
|
|
335
|
+
if (typeof item.command === 'string') {
|
|
336
|
+
this.props.commandRegistry.executeCommand(item.command);
|
|
337
|
+
} else {
|
|
338
|
+
this.props.commandRegistry.executeCommand(item.command.id, ...(item.command.arguments ?? []));
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}}>
|
|
342
|
+
{content}
|
|
343
|
+
</div>;
|
|
344
|
+
}
|
|
345
|
+
|
|
285
346
|
}
|
|
286
347
|
|
|
287
348
|
interface NotebookCellOutputProps {
|
|
@@ -152,17 +152,17 @@ export class NotebookMainToolbar extends React.Component<NotebookMainToolbarProp
|
|
|
152
152
|
|
|
153
153
|
override render(): React.ReactNode {
|
|
154
154
|
const menuItems = this.getMenuItems();
|
|
155
|
-
return <div className='theia-notebook-main-toolbar'>
|
|
155
|
+
return <div className='theia-notebook-main-toolbar' id='notebook-main-toolbar'>
|
|
156
156
|
{menuItems.slice(0, menuItems.length - this.calculateNumberOfHiddenItems(menuItems)).map(item => this.renderMenuItem(item))}
|
|
157
157
|
{
|
|
158
158
|
this.state.numberOfHiddenItems > 0 &&
|
|
159
159
|
<span className={`${codicon('ellipsis')} action-label theia-notebook-main-toolbar-item`} onClick={e => this.renderContextMenu(e.nativeEvent, menuItems)} />
|
|
160
160
|
}
|
|
161
161
|
<div ref={element => this.gapElementChanged(element)} style={{ flexGrow: 1 }}></div>
|
|
162
|
-
<div className='theia-notebook-main-toolbar-item action-label'
|
|
162
|
+
<div className='theia-notebook-main-toolbar-item action-label' id={NotebookCommands.SELECT_KERNEL_COMMAND.id}
|
|
163
163
|
onClick={() => this.props.commandRegistry.executeCommand(NotebookCommands.SELECT_KERNEL_COMMAND.id, this.props.notebookModel)}>
|
|
164
164
|
<span className={codicon('server-environment')} />
|
|
165
|
-
<span className=' theia-notebook-main-toolbar-item-text'>
|
|
165
|
+
<span className=' theia-notebook-main-toolbar-item-text' id='kernel-text'>
|
|
166
166
|
{this.state.selectedKernelLabel ?? nls.localizeByDefault('Select Kernel')}
|
|
167
167
|
</span>
|
|
168
168
|
</div>
|
|
@@ -195,7 +195,7 @@ export class NotebookMainToolbar extends React.Component<NotebookMainToolbarProp
|
|
|
195
195
|
const command = this.props.commandRegistry.getCommand(item.command ?? '') as NotebookCommand | undefined;
|
|
196
196
|
const label = command?.shortTitle ?? item.label;
|
|
197
197
|
const title = command?.tooltip ?? item.label;
|
|
198
|
-
return <div key={item.id} title={title} className={`theia-notebook-main-toolbar-item action-label${this.getAdditionalClasses(item)}`}
|
|
198
|
+
return <div key={item.id} id={item.id} title={title} className={`theia-notebook-main-toolbar-item action-label${this.getAdditionalClasses(item)}`}
|
|
199
199
|
onClick={() => {
|
|
200
200
|
if (item.command && (!item.when || this.props.contextKeyService.match(item.when, this.props.editorNode))) {
|
|
201
201
|
this.props.commandRegistry.executeCommand(item.command, this.props.notebookModel.uri);
|
|
@@ -30,6 +30,8 @@ import { NotebookCodeCellStatus } from './notebook-code-cell-view';
|
|
|
30
30
|
import { NotebookEditorFindMatch, NotebookEditorFindMatchOptions } from './notebook-find-widget';
|
|
31
31
|
import * as mark from 'advanced-mark.js';
|
|
32
32
|
import { NotebookCellEditorService } from '../service/notebook-cell-editor-service';
|
|
33
|
+
import { NotebookCellStatusBarService } from '../service/notebook-cell-status-bar-service';
|
|
34
|
+
import { LabelParser } from '@theia/core/lib/browser/label-parser';
|
|
33
35
|
|
|
34
36
|
@injectable()
|
|
35
37
|
export class NotebookMarkdownCellRenderer implements CellRenderer {
|
|
@@ -51,6 +53,12 @@ export class NotebookMarkdownCellRenderer implements CellRenderer {
|
|
|
51
53
|
@inject(NotebookCellEditorService)
|
|
52
54
|
protected readonly notebookCellEditorService: NotebookCellEditorService;
|
|
53
55
|
|
|
56
|
+
@inject(NotebookCellStatusBarService)
|
|
57
|
+
protected readonly notebookCellStatusBarService: NotebookCellStatusBarService;
|
|
58
|
+
|
|
59
|
+
@inject(LabelParser)
|
|
60
|
+
protected readonly labelParser: LabelParser;
|
|
61
|
+
|
|
54
62
|
render(notebookModel: NotebookModel, cell: NotebookCellModel): React.ReactNode {
|
|
55
63
|
return <MarkdownCell
|
|
56
64
|
markdownRenderer={this.markdownRenderer}
|
|
@@ -60,7 +68,10 @@ export class NotebookMarkdownCellRenderer implements CellRenderer {
|
|
|
60
68
|
cell={cell}
|
|
61
69
|
notebookModel={notebookModel}
|
|
62
70
|
notebookContextManager={this.notebookContextManager}
|
|
63
|
-
notebookCellEditorService={this.notebookCellEditorService}
|
|
71
|
+
notebookCellEditorService={this.notebookCellEditorService}
|
|
72
|
+
notebookCellStatusBarService={this.notebookCellStatusBarService}
|
|
73
|
+
labelParser={this.labelParser}
|
|
74
|
+
/>;
|
|
64
75
|
}
|
|
65
76
|
|
|
66
77
|
renderSidebar(notebookModel: NotebookModel, cell: NotebookCellModel): React.ReactNode {
|
|
@@ -86,11 +97,15 @@ interface MarkdownCellProps {
|
|
|
86
97
|
notebookModel: NotebookModel;
|
|
87
98
|
notebookContextManager: NotebookContextManager;
|
|
88
99
|
notebookOptionsService: NotebookOptionsService;
|
|
89
|
-
notebookCellEditorService: NotebookCellEditorService
|
|
100
|
+
notebookCellEditorService: NotebookCellEditorService;
|
|
101
|
+
notebookCellStatusBarService: NotebookCellStatusBarService;
|
|
102
|
+
labelParser: LabelParser;
|
|
90
103
|
}
|
|
91
104
|
|
|
92
105
|
function MarkdownCell({
|
|
93
|
-
markdownRenderer, monacoServices, cell, notebookModel, notebookContextManager,
|
|
106
|
+
markdownRenderer, monacoServices, cell, notebookModel, notebookContextManager,
|
|
107
|
+
notebookOptionsService, commandRegistry, notebookCellEditorService, notebookCellStatusBarService,
|
|
108
|
+
labelParser
|
|
94
109
|
}: MarkdownCellProps): React.JSX.Element {
|
|
95
110
|
const [editMode, setEditMode] = React.useState(cell.editing);
|
|
96
111
|
let empty = false;
|
|
@@ -147,6 +162,8 @@ function MarkdownCell({
|
|
|
147
162
|
fontInfo={notebookOptionsService.editorFontInfo} />
|
|
148
163
|
<NotebookCodeCellStatus cell={cell} notebook={notebookModel}
|
|
149
164
|
commandRegistry={commandRegistry}
|
|
165
|
+
cellStatusBarService={notebookCellStatusBarService}
|
|
166
|
+
labelParser={labelParser}
|
|
150
167
|
onClick={() => cell.requestFocusEditor()} />
|
|
151
168
|
</div >) :
|
|
152
169
|
(<div className='theia-notebook-markdown-content' key="markdown"
|
|
@@ -62,6 +62,10 @@ export interface NotebookCell {
|
|
|
62
62
|
metadata: NotebookCellMetadata;
|
|
63
63
|
internalMetadata: NotebookCellInternalMetadata;
|
|
64
64
|
text: string;
|
|
65
|
+
/**
|
|
66
|
+
* The selection of the cell. Zero-based line/character coordinates.
|
|
67
|
+
*/
|
|
68
|
+
selection: Range | undefined;
|
|
65
69
|
onDidChangeOutputs?: Event<NotebookCellOutputsSplice>;
|
|
66
70
|
onDidChangeOutputItems?: Event<CellOutput>;
|
|
67
71
|
onDidChangeLanguage: Event<string>;
|
|
@@ -254,14 +258,26 @@ export class NotebookCellModel implements NotebookCell, Disposable {
|
|
|
254
258
|
}
|
|
255
259
|
}
|
|
256
260
|
|
|
261
|
+
protected _selection: Range | undefined = undefined;
|
|
262
|
+
|
|
263
|
+
get selection(): Range | undefined {
|
|
264
|
+
return this._selection;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
set selection(selection: Range | undefined) {
|
|
268
|
+
this._selection = selection;
|
|
269
|
+
}
|
|
270
|
+
|
|
257
271
|
protected _cellheight: number = 0;
|
|
258
272
|
get cellHeight(): number {
|
|
259
273
|
return this._cellheight;
|
|
260
274
|
}
|
|
261
275
|
|
|
262
276
|
set cellHeight(height: number) {
|
|
263
|
-
this.
|
|
264
|
-
|
|
277
|
+
if (height !== this._cellheight) {
|
|
278
|
+
this.onDidCellHeightChangeEmitter.fire(height);
|
|
279
|
+
this._cellheight = height;
|
|
280
|
+
}
|
|
265
281
|
}
|
|
266
282
|
|
|
267
283
|
@postConstruct()
|