forked from jupyterlab/jupyterlab
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tracker.ts
140 lines (120 loc) · 3.72 KB
/
tracker.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
import { IInstanceTracker, InstanceTracker } from '@jupyterlab/apputils';
import { Cell } from '@jupyterlab/cells';
import { Token } from '@phosphor/coreutils';
import { ISignal, Signal } from '@phosphor/signaling';
import { NotebookPanel, Notebook } from './';
/**
* An object that tracks notebook widgets.
*/
export interface INotebookTracker extends IInstanceTracker<NotebookPanel> {
/**
* The currently focused cell.
*
* #### Notes
* If there is no cell with the focus, then this value is `null`.
*/
readonly activeCell: Cell;
/**
* A signal emitted when the current active cell changes.
*
* #### Notes
* If there is no cell with the focus, then `null` will be emitted.
*/
readonly activeCellChanged: ISignal<this, Cell>;
/**
* A signal emitted when the selection state changes.
*/
readonly selectionChanged: ISignal<this, void>;
}
/* tslint:disable */
/**
* The notebook tracker token.
*/
export const INotebookTracker = new Token<INotebookTracker>(
'@jupyterlab/notebook:INotebookTracker'
);
/* tslint:enable */
export class NotebookTracker extends InstanceTracker<NotebookPanel>
implements INotebookTracker {
/**
* The currently focused cell.
*
* #### Notes
* This is a read-only property. If there is no cell with the focus, then this
* value is `null`.
*/
get activeCell(): Cell {
let widget = this.currentWidget;
if (!widget) {
return null;
}
return widget.content.activeCell || null;
}
/**
* A signal emitted when the current active cell changes.
*
* #### Notes
* If there is no cell with the focus, then `null` will be emitted.
*/
get activeCellChanged(): ISignal<this, Cell> {
return this._activeCellChanged;
}
/**
* A signal emitted when the selection state changes.
*/
get selectionChanged(): ISignal<this, void> {
return this._selectionChanged;
}
/**
* Add a new notebook panel to the tracker.
*
* @param panel - The notebook panel being added.
*/
add(panel: NotebookPanel): Promise<void> {
const promise = super.add(panel);
panel.content.activeCellChanged.connect(this._onActiveCellChanged, this);
panel.content.selectionChanged.connect(this._onSelectionChanged, this);
return promise;
}
/**
* Dispose of the resources held by the tracker.
*/
dispose(): void {
this._activeCell = null;
super.dispose();
}
/**
* Handle the current change event.
*/
protected onCurrentChanged(widget: NotebookPanel): void {
// Store an internal reference to active cell to prevent false positives.
let activeCell = this.activeCell;
if (activeCell && activeCell === this._activeCell) {
return;
}
this._activeCell = activeCell;
if (!widget) {
return;
}
// Since the notebook has changed, immediately signal an active cell change
this._activeCellChanged.emit(widget.content.activeCell || null);
}
private _onActiveCellChanged(sender: Notebook, cell: Cell): void {
// Check if the active cell change happened for the current notebook.
if (this.currentWidget && this.currentWidget.content === sender) {
this._activeCell = cell || null;
this._activeCellChanged.emit(this._activeCell);
}
}
private _onSelectionChanged(sender: Notebook): void {
// Check if the selection change happened for the current notebook.
if (this.currentWidget && this.currentWidget.content === sender) {
this._selectionChanged.emit(void 0);
}
}
private _activeCell: Cell | null = null;
private _activeCellChanged = new Signal<this, Cell>(this);
private _selectionChanged = new Signal<this, void>(this);
}