|
@@ -6,7 +6,11 @@ import {
|
|
} from 'jupyter-js-services';
|
|
} from 'jupyter-js-services';
|
|
|
|
|
|
import {
|
|
import {
|
|
- Message
|
|
|
|
|
|
+ find
|
|
|
|
+} from 'phosphor/lib/algorithm/searching';
|
|
|
|
+
|
|
|
|
+import {
|
|
|
|
+ sendMessage, Message
|
|
} from 'phosphor/lib/core/messaging';
|
|
} from 'phosphor/lib/core/messaging';
|
|
|
|
|
|
import {
|
|
import {
|
|
@@ -26,7 +30,7 @@ import {
|
|
} from 'phosphor/lib/ui/panel';
|
|
} from 'phosphor/lib/ui/panel';
|
|
|
|
|
|
import {
|
|
import {
|
|
- Widget
|
|
|
|
|
|
+ Widget, WidgetMessage
|
|
} from 'phosphor/lib/ui/widget';
|
|
} from 'phosphor/lib/ui/widget';
|
|
|
|
|
|
import {
|
|
import {
|
|
@@ -600,6 +604,8 @@ class Notebook extends StaticNotebook {
|
|
return this._mode;
|
|
return this._mode;
|
|
}
|
|
}
|
|
set mode(newValue: NotebookMode) {
|
|
set mode(newValue: NotebookMode) {
|
|
|
|
+ // Always post an update request.
|
|
|
|
+ this.update();
|
|
if (newValue === this._mode) {
|
|
if (newValue === this._mode) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -617,17 +623,13 @@ class Notebook extends StaticNotebook {
|
|
let widget = layout.widgets.at(i) as BaseCellWidget;
|
|
let widget = layout.widgets.at(i) as BaseCellWidget;
|
|
this.deselect(widget);
|
|
this.deselect(widget);
|
|
}
|
|
}
|
|
- activeCell.activate();
|
|
|
|
if (activeCell instanceof MarkdownCellWidget) {
|
|
if (activeCell instanceof MarkdownCellWidget) {
|
|
activeCell.rendered = false;
|
|
activeCell.rendered = false;
|
|
}
|
|
}
|
|
- } else {
|
|
|
|
- // Take focus if the active cell is focused.
|
|
|
|
- if (activeCell.editor.hasFocus()) {
|
|
|
|
- this.node.focus();
|
|
|
|
|
|
+ if (!this._isActive) {
|
|
|
|
+ sendMessage(this, WidgetMessage.ActivateRequest);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- this.update();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -643,6 +645,8 @@ class Notebook extends StaticNotebook {
|
|
return this.model.cells.length ? this._activeCellIndex : -1;
|
|
return this.model.cells.length ? this._activeCellIndex : -1;
|
|
}
|
|
}
|
|
set activeCellIndex(newValue: number) {
|
|
set activeCellIndex(newValue: number) {
|
|
|
|
+ // Always post an update request.
|
|
|
|
+ this.update();
|
|
let oldValue = this._activeCellIndex;
|
|
let oldValue = this._activeCellIndex;
|
|
if (!this.model || !this.model.cells.length) {
|
|
if (!this.model || !this.model.cells.length) {
|
|
newValue = -1;
|
|
newValue = -1;
|
|
@@ -659,11 +663,7 @@ class Notebook extends StaticNotebook {
|
|
if (newValue === oldValue) {
|
|
if (newValue === oldValue) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- if (this.mode === 'edit' && this.activeCell) {
|
|
|
|
- this.activeCell.activate();
|
|
|
|
- }
|
|
|
|
this.stateChanged.emit({ name: 'activeCellIndex', oldValue, newValue });
|
|
this.stateChanged.emit({ name: 'activeCellIndex', oldValue, newValue });
|
|
- this.update();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -751,6 +751,9 @@ class Notebook extends StaticNotebook {
|
|
* not be called directly by user code.
|
|
* not be called directly by user code.
|
|
*/
|
|
*/
|
|
handleEvent(event: Event): void {
|
|
handleEvent(event: Event): void {
|
|
|
|
+ if (!this.model || this.model.readOnly) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
switch (event.type) {
|
|
switch (event.type) {
|
|
case 'mousedown':
|
|
case 'mousedown':
|
|
this._evtMouseDown(event as MouseEvent);
|
|
this._evtMouseDown(event as MouseEvent);
|
|
@@ -774,7 +777,6 @@ class Notebook extends StaticNotebook {
|
|
this.node.addEventListener('mousedown', this);
|
|
this.node.addEventListener('mousedown', this);
|
|
this.node.addEventListener('dblclick', this);
|
|
this.node.addEventListener('dblclick', this);
|
|
this.node.addEventListener('focus', this, true);
|
|
this.node.addEventListener('focus', this, true);
|
|
- this.update();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -790,7 +792,7 @@ class Notebook extends StaticNotebook {
|
|
* Handle `'activate-request'` messages.
|
|
* Handle `'activate-request'` messages.
|
|
*/
|
|
*/
|
|
protected onActivateRequest(msg: Message): void {
|
|
protected onActivateRequest(msg: Message): void {
|
|
- this.node.focus();
|
|
|
|
|
|
+ this._isActive = true;
|
|
this.update();
|
|
this.update();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -798,16 +800,36 @@ class Notebook extends StaticNotebook {
|
|
* Handle `'deactivate-request'` messages.
|
|
* Handle `'deactivate-request'` messages.
|
|
*/
|
|
*/
|
|
protected onDeactivateRequest(msg: Message): void {
|
|
protected onDeactivateRequest(msg: Message): void {
|
|
|
|
+ this._isActive = false;
|
|
this.mode = 'command';
|
|
this.mode = 'command';
|
|
- this.update();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* Handle `update-request` messages sent to the widget.
|
|
* Handle `update-request` messages sent to the widget.
|
|
*/
|
|
*/
|
|
protected onUpdateRequest(msg: Message): void {
|
|
protected onUpdateRequest(msg: Message): void {
|
|
- // Set the appropriate classes on the cells.
|
|
|
|
let activeCell = this.activeCell;
|
|
let activeCell = this.activeCell;
|
|
|
|
+ // Ensure we have the correct focus.
|
|
|
|
+ if (this._isActive) {
|
|
|
|
+ if (this.mode === 'edit' && activeCell) {
|
|
|
|
+ activeCell.editor.activate();
|
|
|
|
+ } else {
|
|
|
|
+ // Focus the node if nothing is focused internally.
|
|
|
|
+ if (!this.node.contains(document.activeElement)) {
|
|
|
|
+ this.node.focus();
|
|
|
|
+ } else {
|
|
|
|
+ // If an editor currently has focus, focus the node.
|
|
|
|
+ // Otherwise, another input field has focus and should keep it.
|
|
|
|
+ let w = find(this.layout, widget => {
|
|
|
|
+ return (widget as BaseCellWidget).editor.hasFocus();
|
|
|
|
+ });
|
|
|
|
+ if (w) {
|
|
|
|
+ this.node.focus();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // Set the appropriate classes on the cells.
|
|
if (this.mode === 'edit') {
|
|
if (this.mode === 'edit') {
|
|
this.addClass(EDIT_CLASS);
|
|
this.addClass(EDIT_CLASS);
|
|
this.removeClass(COMMAND_CLASS);
|
|
this.removeClass(COMMAND_CLASS);
|
|
@@ -846,7 +868,6 @@ class Notebook extends StaticNotebook {
|
|
cell.editor.edgeRequested.connect(this._onEdgeRequest, this);
|
|
cell.editor.edgeRequested.connect(this._onEdgeRequest, this);
|
|
// Trigger an update of the active cell.
|
|
// Trigger an update of the active cell.
|
|
this.activeCellIndex = this.activeCellIndex;
|
|
this.activeCellIndex = this.activeCellIndex;
|
|
- this.update();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -867,7 +888,6 @@ class Notebook extends StaticNotebook {
|
|
if (this.isSelected(cell)) {
|
|
if (this.isSelected(cell)) {
|
|
this.selectionChanged.emit(void 0);
|
|
this.selectionChanged.emit(void 0);
|
|
}
|
|
}
|
|
- this.update();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -928,8 +948,8 @@ class Notebook extends StaticNotebook {
|
|
* Handle `mousedown` events for the widget.
|
|
* Handle `mousedown` events for the widget.
|
|
*/
|
|
*/
|
|
private _evtMouseDown(event: MouseEvent): void {
|
|
private _evtMouseDown(event: MouseEvent): void {
|
|
- if (!this.model || this.model.readOnly) {
|
|
|
|
- return;
|
|
|
|
|
|
+ if (!this._isActive) {
|
|
|
|
+ sendMessage(this, WidgetMessage.ActivateRequest);
|
|
}
|
|
}
|
|
let target = event.target as HTMLElement;
|
|
let target = event.target as HTMLElement;
|
|
let i = this._findCell(target);
|
|
let i = this._findCell(target);
|
|
@@ -940,15 +960,18 @@ class Notebook extends StaticNotebook {
|
|
this.mode = 'command';
|
|
this.mode = 'command';
|
|
}
|
|
}
|
|
// Set the cell as the active one.
|
|
// Set the cell as the active one.
|
|
|
|
+ // This must be done *after* setting the mode above.
|
|
this.activeCellIndex = i;
|
|
this.activeCellIndex = i;
|
|
}
|
|
}
|
|
- this.update();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* Handle `focus` events for the widget.
|
|
* Handle `focus` events for the widget.
|
|
*/
|
|
*/
|
|
private _evtFocus(event: MouseEvent): void {
|
|
private _evtFocus(event: MouseEvent): void {
|
|
|
|
+ if (!this._isActive) {
|
|
|
|
+ sendMessage(this, WidgetMessage.ActivateRequest);
|
|
|
|
+ }
|
|
let target = event.target as HTMLElement;
|
|
let target = event.target as HTMLElement;
|
|
let i = this._findCell(target);
|
|
let i = this._findCell(target);
|
|
if (i !== -1) {
|
|
if (i !== -1) {
|
|
@@ -961,17 +984,20 @@ class Notebook extends StaticNotebook {
|
|
} else {
|
|
} else {
|
|
this.mode = 'command';
|
|
this.mode = 'command';
|
|
}
|
|
}
|
|
|
|
+ this.activeCellIndex = i;
|
|
} else {
|
|
} else {
|
|
// No cell has focus, ensure command mode.
|
|
// No cell has focus, ensure command mode.
|
|
this.mode = 'command';
|
|
this.mode = 'command';
|
|
}
|
|
}
|
|
- this.update();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* Handle `dblclick` events for the widget.
|
|
* Handle `dblclick` events for the widget.
|
|
*/
|
|
*/
|
|
private _evtDblClick(event: MouseEvent): void {
|
|
private _evtDblClick(event: MouseEvent): void {
|
|
|
|
+ if (!this._isActive) {
|
|
|
|
+ sendMessage(this, WidgetMessage.ActivateRequest);
|
|
|
|
+ }
|
|
let model = this.model;
|
|
let model = this.model;
|
|
if (!model || model.readOnly) {
|
|
if (!model || model.readOnly) {
|
|
return;
|
|
return;
|
|
@@ -996,6 +1022,7 @@ class Notebook extends StaticNotebook {
|
|
private _activeCell: BaseCellWidget = null;
|
|
private _activeCell: BaseCellWidget = null;
|
|
private _inspectionHandler: InspectionHandler = null;
|
|
private _inspectionHandler: InspectionHandler = null;
|
|
private _mode: NotebookMode = 'command';
|
|
private _mode: NotebookMode = 'command';
|
|
|
|
+ private _isActive = false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|