@@ -8,7 +8,8 @@ import * as DOM from 'vs/base/browser/dom';
88import { IListRenderer , IListVirtualDelegate } from 'vs/base/browser/ui/list/list' ;
99import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar' ;
1010import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar' ;
11- import { IAction } from 'vs/base/common/actions' ;
11+ import { IAction , ActionRunner } from 'vs/base/common/actions' ;
12+ import { escape } from 'vs/base/common/strings' ;
1213import { DisposableStore } from 'vs/base/common/lifecycle' ;
1314import { deepClone } from 'vs/base/common/objects' ;
1415import 'vs/css!vs/workbench/contrib/notebook/browser/notebook' ;
@@ -24,8 +25,8 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
2425import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation' ;
2526import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding' ;
2627import { INotificationService } from 'vs/platform/notification/common/notification' ;
27- import { EDITOR_BOTTOM_PADDING , EDITOR_TOOLBAR_HEIGHT , EDITOR_TOP_MARGIN , EDITOR_TOP_PADDING , NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY , NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY , NOTEBOOK_CELL_TYPE_CONTEXT_KEY , NOTEBOOK_CELL_RUN_STATE_CONTEXT_KEY , NOTEBOOK_VIEW_TYPE } from 'vs/workbench/contrib/notebook/browser/constants' ;
28- import { ExecuteCellAction , INotebookCellActionContext , CancelCellAction } from 'vs/workbench/contrib/notebook/browser/contrib/notebookActions' ;
28+ import { EDITOR_BOTTOM_PADDING , EDITOR_TOOLBAR_HEIGHT , EDITOR_TOP_MARGIN , EDITOR_TOP_PADDING , NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY , NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY , NOTEBOOK_CELL_TYPE_CONTEXT_KEY , NOTEBOOK_CELL_RUN_STATE_CONTEXT_KEY , NOTEBOOK_VIEW_TYPE , BOTTOM_CELL_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants' ;
29+ import { ExecuteCellAction , INotebookCellActionContext , CancelCellAction , InsertCodeCellAction , InsertMarkdownCellAction } from 'vs/workbench/contrib/notebook/browser/contrib/notebookActions' ;
2930import { BaseCellRenderTemplate , CellEditState , CellRunState , CodeCellRenderTemplate , ICellViewModel , INotebookEditor , MarkdownCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser' ;
3031import { CellMenus } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellMenus' ;
3132import { CodeCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/codeCell' ;
@@ -34,12 +35,12 @@ import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewMod
3435import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel' ;
3536import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel' ;
3637import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon' ;
38+ import { renderCodicons } from 'vs/base/common/codicons' ;
3739
3840const $ = DOM . $ ;
3941
4042export class NotebookCellListDelegate implements IListVirtualDelegate < CellViewModel > {
4143 private _lineHeight : number ;
42- private _toolbarHeight = EDITOR_TOOLBAR_HEIGHT ;
4344
4445 constructor (
4546 @IConfigurationService private readonly configurationService : IConfigurationService
@@ -49,7 +50,7 @@ export class NotebookCellListDelegate implements IListVirtualDelegate<CellViewMo
4950 }
5051
5152 getHeight ( element : CellViewModel ) : number {
52- return element . getHeight ( this . _lineHeight ) + this . _toolbarHeight ;
53+ return element . getHeight ( this . _lineHeight ) ;
5354 }
5455
5556 hasDynamicHeight ( element : CellViewModel ) : boolean {
@@ -65,6 +66,22 @@ export class NotebookCellListDelegate implements IListVirtualDelegate<CellViewMo
6566 }
6667}
6768
69+ export class CodiconActionViewItem extends ContextAwareMenuEntryActionViewItem {
70+ constructor (
71+ readonly _action : MenuItemAction ,
72+ _keybindingService : IKeybindingService ,
73+ _notificationService : INotificationService ,
74+ _contextMenuService : IContextMenuService
75+ ) {
76+ super ( _action , _keybindingService , _notificationService , _contextMenuService ) ;
77+ }
78+ updateLabel ( ) : void {
79+ if ( this . options . label && this . label ) {
80+ this . label . innerHTML = renderCodicons ( this . _commandAction . label ?? '' ) ;
81+ }
82+ }
83+ }
84+
6885abstract class AbstractCellRenderer {
6986 protected editorOptions : IEditorOptions ;
7087
@@ -105,6 +122,22 @@ abstract class AbstractCellRenderer {
105122 } ;
106123 }
107124
125+ protected createBottomCellToolbar ( container : HTMLElement ) : ToolBar {
126+ const toolbar = new ToolBar ( container , this . contextMenuService , {
127+ actionViewItemProvider : action => {
128+ if ( action instanceof MenuItemAction ) {
129+ const item = new CodiconActionViewItem ( action , this . keybindingService , this . notificationService , this . contextMenuService ) ;
130+ return item ;
131+ }
132+
133+ return undefined ;
134+ }
135+ } ) ;
136+
137+ toolbar . getContainer ( ) . style . height = `${ BOTTOM_CELL_TOOLBAR_HEIGHT } px` ;
138+ return toolbar ;
139+ }
140+
108141 protected createToolbar ( container : HTMLElement ) : ToolBar {
109142 const toolbar = new ToolBar ( container , this . contextMenuService , {
110143 actionViewItemProvider : action => {
@@ -258,6 +291,8 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
258291export class CodeCellRenderer extends AbstractCellRenderer implements IListRenderer < CodeCellViewModel , CodeCellRenderTemplate > {
259292 static readonly TEMPLATE_ID = 'code_cell' ;
260293 private disposables : Map < ICellViewModel , DisposableStore > = new Map ( ) ;
294+ private actionRunner = new ActionRunner ( ) ;
295+
261296
262297 constructor (
263298 protected notebookEditor : INotebookEditor ,
@@ -286,6 +321,8 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
286321 const runToolbar = this . createToolbar ( runButtonContainer ) ;
287322 disposables . add ( runToolbar ) ;
288323
324+ const betweenCellContainer = DOM . append ( container , $ ( '.cell-bottom-toolbar-container' ) ) ;
325+
289326 const executionOrderLabel = DOM . append ( runButtonContainer , $ ( 'div.execution-count-label' ) ) ;
290327
291328 const editorContainer = DOM . append ( cellContainer , $ ( '.cell-editor-container' ) ) ;
@@ -320,9 +357,44 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
320357 outputContainer,
321358 editor,
322359 disposables,
360+ betweenCellContainer : betweenCellContainer ,
361+ // betweenCellToolbar: betweenCellActionsToolbar
323362 } ;
324363 }
325364
365+ protected setupBetweenCellToolbarActions ( element : CodeCellViewModel , templateData : CodeCellRenderTemplate , disposables : DisposableStore , context : INotebookCellActionContext ) : void {
366+ const container = templateData . betweenCellContainer ;
367+ container . innerHTML = '' ;
368+ container . style . height = `${ BOTTOM_CELL_TOOLBAR_HEIGHT } px` ;
369+
370+ DOM . append ( container , $ ( '.seperator' ) ) ;
371+ const addCodeCell = DOM . append ( container , $ ( 'span.button' ) ) ;
372+ addCodeCell . innerHTML = renderCodicons ( escape ( `$(add) Code ` ) ) ;
373+ const insertCellBelow = this . instantiationService . createInstance ( InsertCodeCellAction ) ;
374+
375+ disposables . add ( DOM . addDisposableListener ( addCodeCell , DOM . EventType . CLICK , ( ) => {
376+ this . actionRunner . run ( insertCellBelow , context ) ;
377+ } ) ) ;
378+
379+ DOM . append ( container , $ ( '.seperator-short' ) ) ;
380+ const addMarkdownCell = DOM . append ( container , $ ( 'span.button' ) ) ;
381+ addMarkdownCell . innerHTML = renderCodicons ( escape ( '$(add) Markdown ' ) ) ;
382+ const insertMarkdownBelow = this . instantiationService . createInstance ( InsertMarkdownCellAction ) ;
383+ disposables . add ( DOM . addDisposableListener ( addMarkdownCell , DOM . EventType . CLICK , ( ) => {
384+ this . actionRunner . run ( insertMarkdownBelow , context ) ;
385+ } ) ) ;
386+
387+ DOM . append ( container , $ ( '.seperator' ) ) ;
388+
389+ const bottomToolbarOffset = element . layoutInfo . bottomToolbarOffset ;
390+ container . style . top = `${ bottomToolbarOffset } px` ;
391+
392+ disposables . add ( element . onDidChangeLayout ( ( ) => {
393+ const bottomToolbarOffset = element . layoutInfo . bottomToolbarOffset ;
394+ container . style . top = `${ bottomToolbarOffset } px` ;
395+ } ) ) ;
396+ }
397+
326398 private updateForRunState ( element : CodeCellViewModel , templateData : CodeCellRenderTemplate , runStateKey : IContextKey < string > ) : void {
327399 runStateKey . set ( CellRunState [ element . runState ] ) ;
328400 if ( element . runState === CellRunState . Running ) {
@@ -395,6 +467,8 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
395467 } ;
396468 templateData . toolbar . context = toolbarContext ;
397469 templateData . runToolbar . context = toolbarContext ;
470+
471+ this . setupBetweenCellToolbarActions ( element , templateData , elementDisposable , toolbarContext ) ;
398472 }
399473
400474 disposeTemplate ( templateData : CodeCellRenderTemplate ) : void {
0 commit comments