1- import { PromiseDelegate } from '@lumino/coreutils' ;
2- import { TabBar , BoxPanel , Widget } from '@lumino/widgets' ;
3-
41import { Dialog , InputDialog , showDialog } from '@jupyterlab/apputils' ;
5- import { IRenderMimeRegistry } from '@jupyterlab/rendermime' ;
62import { DocumentRegistry } from '@jupyterlab/docregistry' ;
73import { INotebookTracker } from '@jupyterlab/notebook' ;
4+ import { IRenderMimeRegistry } from '@jupyterlab/rendermime' ;
5+ import { IKernelConnection } from '@jupyterlab/services/lib/kernel/kernel' ;
6+ import { CommandRegistry } from '@lumino/commands' ;
7+ import { PromiseDelegate } from '@lumino/coreutils' ;
8+ import { Message } from '@lumino/messaging' ;
9+ import { BoxPanel , TabBar , Widget } from '@lumino/widgets' ;
10+ import { IJupyterYWidgetManager } from 'yjs-widgets' ;
811
12+ import { CommandIDs } from '../commands' ;
913import { HTabPanel } from '../common/tabPanel' ;
10- import { DATASET_MIME , IDict , IGlueSessionSharedModel } from '../types' ;
1114import { GlueSessionModel } from '../document/docModel' ;
15+ import { LinkEditor } from '../linkPanel/linkEditor' ;
1216import { mockNotebook } from '../tools' ;
17+ import { DATASET_MIME , IDict , IGlueSessionSharedModel } from '../types' ;
1318import { TabView } from './tabView' ;
14- import { LinkEditor } from '../linkPanel/linkEditor' ;
15-
16- import { Message } from '@lumino/messaging' ;
17- import { CommandRegistry } from '@lumino/commands' ;
18- import { CommandIDs } from '../commands' ;
19- import { IJupyterYWidgetManager } from 'yjs-widgets' ;
20- import { IKernelConnection } from '@jupyterlab/services/lib/kernel/kernel' ;
2119
2220export class SessionWidget extends BoxPanel {
2321 constructor ( options : SessionWidget . IOptions ) {
@@ -50,6 +48,18 @@ export class SessionWidget extends BoxPanel {
5048 this . _tabPanel . topBar . addRequested . connect ( ( ) => {
5149 this . _model . addTab ( ) ;
5250 } ) ;
51+ this . _tabPanel . topBar . tabCloseRequested . connect ( async ( tab , arg ) => {
52+ const confirm = await showDialog ( {
53+ title : 'Delete Tab' ,
54+ body : 'Are you sure you want to delete this tab?' ,
55+ buttons : [ Dialog . cancelButton ( ) , Dialog . okButton ( { label : 'Delete' } ) ]
56+ } ) ;
57+ if ( confirm . button . accept ) {
58+ arg . title . owner . close ( ) ;
59+ this . _tabPanel . topBar . removeTabAt ( arg . index ) ;
60+ this . _model . removeTab ( arg . title . label ) ;
61+ }
62+ } ) ;
5363 if ( this . _model ) {
5464 this . _linkWidget = new LinkEditor ( { sharedModel : this . _model } ) ;
5565 this . _tabPanel . addTab ( this . _linkWidget , 0 ) ;
@@ -166,7 +176,12 @@ export class SessionWidget extends BoxPanel {
166176 let newTabIndex : number | undefined = undefined ;
167177 const currentIndex = this . _tabPanel . topBar . currentIndex ;
168178 const tabNames = this . _model . getTabNames ( ) ;
169-
179+ Object . keys ( this . _tabViews ) . forEach ( k => {
180+ if ( ! tabNames . includes ( k ) ) {
181+ this . _tabViews [ k ] . dispose ( ) ;
182+ delete this . _tabViews [ k ] ;
183+ }
184+ } ) ;
170185 tabNames . forEach ( ( tabName , idx ) => {
171186 // Tab already exists, we don't do anything
172187 if ( tabName in this . _tabViews ) {
@@ -182,7 +197,7 @@ export class SessionWidget extends BoxPanel {
182197 notebookTracker : this . _notebookTracker ,
183198 commands : this . _commands
184199 } ) ) ;
185-
200+ tabWidget . title . closable = true ;
186201 this . _tabPanel . addTab ( tabWidget , idx + 1 ) ;
187202 } ) ;
188203
0 commit comments