Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/notebook/browser/viewParts/notebookTopCellToolbar.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as DOM from '../../../../../base/browser/dom.js';
7
import { Disposable, DisposableStore, MutableDisposable } from '../../../../../base/common/lifecycle.js';
8
import { HiddenItemStrategy, MenuWorkbenchToolBar } from '../../../../../platform/actions/browser/toolbar.js';
9
import { IMenuService, MenuItemAction } from '../../../../../platform/actions/common/actions.js';
10
import { IContextMenuService } from '../../../../../platform/contextview/browser/contextView.js';
11
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
12
import { INotebookActionContext } from '../controller/coreActions.js';
13
import { INotebookEditorDelegate } from '../notebookBrowser.js';
14
import { NotebookOptions } from '../notebookOptions.js';
15
import { CodiconActionViewItem } from '../view/cellParts/cellActionView.js';
16
17
export class ListTopCellToolbar extends Disposable {
18
private readonly topCellToolbarContainer: HTMLElement;
19
private topCellToolbar: HTMLElement;
20
private readonly viewZone: MutableDisposable<DisposableStore> = this._register(new MutableDisposable());
21
private readonly _modelDisposables = this._register(new DisposableStore());
22
constructor(
23
protected readonly notebookEditor: INotebookEditorDelegate,
24
private readonly notebookOptions: NotebookOptions,
25
@IInstantiationService protected readonly instantiationService: IInstantiationService,
26
@IContextMenuService protected readonly contextMenuService: IContextMenuService,
27
@IMenuService protected readonly menuService: IMenuService
28
) {
29
super();
30
31
this.topCellToolbarContainer = DOM.$('div');
32
this.topCellToolbar = DOM.$('.cell-list-top-cell-toolbar-container');
33
this.topCellToolbarContainer.appendChild(this.topCellToolbar);
34
35
this._register(this.notebookEditor.onDidAttachViewModel(() => {
36
this.updateTopToolbar();
37
}));
38
39
this._register(this.notebookOptions.onDidChangeOptions(e => {
40
if (e.insertToolbarAlignment || e.insertToolbarPosition || e.cellToolbarLocation) {
41
this.updateTopToolbar();
42
}
43
}));
44
}
45
46
private updateTopToolbar() {
47
const layoutInfo = this.notebookOptions.getLayoutConfiguration();
48
this.viewZone.value = new DisposableStore();
49
50
if (layoutInfo.insertToolbarPosition === 'hidden' || layoutInfo.insertToolbarPosition === 'notebookToolbar') {
51
const height = this.notebookOptions.computeTopInsertToolbarHeight(this.notebookEditor.textModel?.viewType);
52
53
if (height !== 0) {
54
// reserve whitespace to avoid overlap with cell toolbar
55
this.notebookEditor.changeViewZones(accessor => {
56
const id = accessor.addZone({
57
afterModelPosition: 0,
58
heightInPx: height,
59
domNode: DOM.$('div')
60
});
61
accessor.layoutZone(id);
62
this.viewZone.value?.add({
63
dispose: () => {
64
if (!this.notebookEditor.isDisposed) {
65
this.notebookEditor.changeViewZones(accessor => {
66
accessor.removeZone(id);
67
});
68
}
69
}
70
});
71
});
72
}
73
return;
74
}
75
76
77
this.notebookEditor.changeViewZones(accessor => {
78
const height = this.notebookOptions.computeTopInsertToolbarHeight(this.notebookEditor.textModel?.viewType);
79
const id = accessor.addZone({
80
afterModelPosition: 0,
81
heightInPx: height,
82
domNode: this.topCellToolbarContainer
83
});
84
accessor.layoutZone(id);
85
86
this.viewZone.value?.add({
87
dispose: () => {
88
if (!this.notebookEditor.isDisposed) {
89
this.notebookEditor.changeViewZones(accessor => {
90
accessor.removeZone(id);
91
});
92
}
93
}
94
});
95
96
DOM.clearNode(this.topCellToolbar);
97
98
const toolbar = this.instantiationService.createInstance(MenuWorkbenchToolBar, this.topCellToolbar, this.notebookEditor.creationOptions.menuIds.cellTopInsertToolbar, {
99
actionViewItemProvider: (action, options) => {
100
if (action instanceof MenuItemAction) {
101
const item = this.instantiationService.createInstance(CodiconActionViewItem, action, { hoverDelegate: options.hoverDelegate });
102
return item;
103
}
104
105
return undefined;
106
},
107
menuOptions: {
108
shouldForwardArgs: true
109
},
110
toolbarOptions: {
111
primaryGroup: (g: string) => /^inline/.test(g),
112
},
113
hiddenItemStrategy: HiddenItemStrategy.Ignore,
114
});
115
116
if (this.notebookEditor.hasModel()) {
117
toolbar.context = {
118
notebookEditor: this.notebookEditor
119
} satisfies INotebookActionContext;
120
}
121
122
this.viewZone.value?.add(toolbar);
123
124
// update toolbar container css based on cell list length
125
this.viewZone.value?.add(this.notebookEditor.onDidChangeModel(() => {
126
this._modelDisposables.clear();
127
128
if (this.notebookEditor.hasModel()) {
129
this._modelDisposables.add(this.notebookEditor.onDidChangeViewCells(() => {
130
this.updateClass();
131
}));
132
133
this.updateClass();
134
}
135
}));
136
137
this.updateClass();
138
});
139
}
140
141
private updateClass() {
142
if (this.notebookEditor.hasModel() && this.notebookEditor.getLength() === 0) {
143
this.topCellToolbar.classList.add('emptyNotebook');
144
} else {
145
this.topCellToolbar.classList.remove('emptyNotebook');
146
}
147
}
148
}
149
150