@jupyterlab/application
Advanced tools
Comparing version 0.3.0 to 0.3.1
import { Application, IPlugin } from '@phosphor/application'; | ||
import { ModuleLoader } from './loader'; | ||
import { ApplicationShell } from './shell'; | ||
export { ModuleLoader } from './loader'; | ||
export { ApplicationShell } from './shell'; | ||
@@ -23,6 +21,2 @@ /** | ||
/** | ||
* The module loader used by the application. | ||
*/ | ||
readonly loader: ModuleLoader | null; | ||
/** | ||
* Promise that resolves when state is restored, returning layout description. | ||
@@ -47,3 +41,2 @@ * | ||
private _info; | ||
private _loader; | ||
} | ||
@@ -63,6 +56,2 @@ /** | ||
/** | ||
* The module loader used by the application. | ||
*/ | ||
loader?: ModuleLoader; | ||
/** | ||
* The namespace/prefix plugins may use to denote their origin. | ||
@@ -69,0 +58,0 @@ * |
@@ -0,4 +1,4 @@ | ||
"use strict"; | ||
// Copyright (c) Jupyter Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
@@ -17,4 +17,2 @@ var extendStatics = Object.setPrototypeOf || | ||
var shell_1 = require("./shell"); | ||
var loader_1 = require("./loader"); | ||
exports.ModuleLoader = loader_1.ModuleLoader; | ||
var shell_2 = require("./shell"); | ||
@@ -38,3 +36,2 @@ exports.ApplicationShell = shell_2.ApplicationShell; | ||
}; | ||
_this._loader = options.loader || null; | ||
return _this; | ||
@@ -52,12 +49,2 @@ } | ||
}); | ||
Object.defineProperty(JupyterLab.prototype, "loader", { | ||
/** | ||
* The module loader used by the application. | ||
*/ | ||
get: function () { | ||
return this._loader; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(JupyterLab.prototype, "restored", { | ||
@@ -64,0 +51,0 @@ /** |
@@ -0,3 +1,5 @@ | ||
import { IIterator } from '@phosphor/algorithm'; | ||
import { Message } from '@phosphor/messaging'; | ||
import { ISignal } from '@phosphor/signaling'; | ||
import { DockLayout, FocusTracker, Widget } from '@phosphor/widgets'; | ||
import { DockLayout, DockPanel, FocusTracker, Widget } from '@phosphor/widgets'; | ||
/** | ||
@@ -12,2 +14,10 @@ * The application shell for JupyterLab. | ||
/** | ||
* A signal emitted when main area's active focus changes. | ||
*/ | ||
readonly activeChanged: ISignal<this, ApplicationShell.IChangedArgs>; | ||
/** | ||
* The active widget in the shell's main area. | ||
*/ | ||
readonly activeWidget: Widget | null; | ||
/** | ||
* A signal emitted when main area's current focus changes. | ||
@@ -17,6 +27,2 @@ */ | ||
/** | ||
* A signal emitted when main area's active focus changes. | ||
*/ | ||
readonly activeChanged: ISignal<this, ApplicationShell.IChangedArgs>; | ||
/** | ||
* The current widget in the shell's main area. | ||
@@ -26,9 +32,9 @@ */ | ||
/** | ||
* The active widget in the shell's main area. | ||
* A signal emitted when the main area's layout is modified. | ||
*/ | ||
readonly activeWidget: Widget | null; | ||
readonly layoutModified: ISignal<this, void>; | ||
/** | ||
* True if the given area is empty. | ||
* The main dock area's user interface mode. | ||
*/ | ||
isEmpty(area: ApplicationShell.Area): boolean; | ||
mode: DockPanel.Mode; | ||
/** | ||
@@ -39,3 +45,3 @@ * Promise that resolves when state is restored, returning layout description. | ||
/** | ||
* Activate a widget in it's area. | ||
* Activate a widget in its area. | ||
*/ | ||
@@ -88,12 +94,23 @@ activateById(id: string): void; | ||
/** | ||
* True if the given area is empty. | ||
*/ | ||
isEmpty(area: ApplicationShell.Area): boolean; | ||
/** | ||
* Set the layout data store for the application shell. | ||
*/ | ||
setLayoutDB(database: ApplicationShell.ILayoutDB): void; | ||
/** | ||
* Returns the widgets for an application area. | ||
*/ | ||
widgets(area: ApplicationShell.Area): IIterator<Widget>; | ||
/** | ||
* Handle `after-attach` messages for the application shell. | ||
*/ | ||
protected onAfterAttach(msg: Message): void; | ||
private _adjacentBar(direction); | ||
private _currentTabBar(); | ||
private _previousTabBar(); | ||
private _nextTabBar(); | ||
/** | ||
* Save the dehydrated state of the application shell. | ||
* Handle a change to the dock area active widget. | ||
*/ | ||
private _save(); | ||
private _onActiveChanged(sender, args); | ||
/** | ||
@@ -104,5 +121,8 @@ * Handle a change to the dock area current widget. | ||
/** | ||
* Handle a change to the dock area active widget. | ||
* Save the dehydrated state of the application shell. | ||
*/ | ||
private _onActiveChanged(sender, args); | ||
private _save(); | ||
private _activeChanged; | ||
private _cachedLayout; | ||
private _currentChanged; | ||
private _database; | ||
@@ -113,9 +133,8 @@ private _dockPanel; | ||
private _isRestored; | ||
private _layoutModified; | ||
private _leftHandler; | ||
private _restored; | ||
private _rightHandler; | ||
private _tracker; | ||
private _topPanel; | ||
private _tracker; | ||
private _currentChanged; | ||
private _activeChanged; | ||
} | ||
@@ -194,2 +213,6 @@ /** | ||
readonly dock: DockLayout.ILayoutConfig | null; | ||
/** | ||
* The document mode (i.e., multiple/single) of the main dock panel. | ||
*/ | ||
readonly mode: DockPanel.Mode | null; | ||
} | ||
@@ -196,0 +219,0 @@ /** |
301
lib/shell.js
@@ -0,4 +1,4 @@ | ||
"use strict"; | ||
// Copyright (c) Jupyter Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
@@ -37,2 +37,10 @@ var extendStatics = Object.setPrototypeOf || | ||
/** | ||
* The default rank of items added to a sidebar. | ||
*/ | ||
var DEFAULT_RANK = 500; | ||
/** | ||
* The data attribute added to the document body indicating shell's mode. | ||
*/ | ||
var MODE_ATTRIBUTE = 'data-shell-mode'; | ||
/** | ||
* The application shell for JupyterLab. | ||
@@ -47,8 +55,10 @@ */ | ||
var _this = _super.call(this) || this; | ||
_this._activeChanged = new signaling_1.Signal(_this); | ||
_this._cachedLayout = null; | ||
_this._currentChanged = new signaling_1.Signal(_this); | ||
_this._database = null; | ||
_this._isRestored = false; | ||
_this._layoutModified = new signaling_1.Signal(_this); | ||
_this._restored = new coreutils_1.PromiseDelegate(); | ||
_this._tracker = new widgets_1.FocusTracker(); | ||
_this._currentChanged = new signaling_1.Signal(_this); | ||
_this._activeChanged = new signaling_1.Signal(_this); | ||
_this.addClass(APPLICATION_SHELL_CLASS); | ||
@@ -101,11 +111,14 @@ _this.id = 'main'; | ||
// Connect main layout change listener. | ||
_this._dockPanel.layoutModified.connect(_this._save, _this); | ||
_this._dockPanel.layoutModified.connect(function () { | ||
_this._layoutModified.emit(void 0); | ||
_this._save(); | ||
}, _this); | ||
return _this; | ||
} | ||
Object.defineProperty(ApplicationShell.prototype, "currentChanged", { | ||
Object.defineProperty(ApplicationShell.prototype, "activeChanged", { | ||
/** | ||
* A signal emitted when main area's current focus changes. | ||
* A signal emitted when main area's active focus changes. | ||
*/ | ||
get: function () { | ||
return this._currentChanged; | ||
return this._activeChanged; | ||
}, | ||
@@ -115,8 +128,8 @@ enumerable: true, | ||
}); | ||
Object.defineProperty(ApplicationShell.prototype, "activeChanged", { | ||
Object.defineProperty(ApplicationShell.prototype, "activeWidget", { | ||
/** | ||
* A signal emitted when main area's active focus changes. | ||
* The active widget in the shell's main area. | ||
*/ | ||
get: function () { | ||
return this._activeChanged; | ||
return this._tracker.activeWidget; | ||
}, | ||
@@ -126,2 +139,12 @@ enumerable: true, | ||
}); | ||
Object.defineProperty(ApplicationShell.prototype, "currentChanged", { | ||
/** | ||
* A signal emitted when main area's current focus changes. | ||
*/ | ||
get: function () { | ||
return this._currentChanged; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(ApplicationShell.prototype, "currentWidget", { | ||
@@ -137,8 +160,8 @@ /** | ||
}); | ||
Object.defineProperty(ApplicationShell.prototype, "activeWidget", { | ||
Object.defineProperty(ApplicationShell.prototype, "layoutModified", { | ||
/** | ||
* The active widget in the shell's main area. | ||
* A signal emitted when the main area's layout is modified. | ||
*/ | ||
get: function () { | ||
return this._tracker.activeWidget; | ||
return this._layoutModified; | ||
}, | ||
@@ -148,19 +171,53 @@ enumerable: true, | ||
}); | ||
/** | ||
* True if the given area is empty. | ||
*/ | ||
ApplicationShell.prototype.isEmpty = function (area) { | ||
switch (area) { | ||
case 'left': | ||
return this._leftHandler.stackedPanel.widgets.length === 0; | ||
case 'main': | ||
return this._dockPanel.isEmpty; | ||
case 'top': | ||
return this._topPanel.widgets.length === 0; | ||
case 'right': | ||
return this._rightHandler.stackedPanel.widgets.length === 0; | ||
default: | ||
return true; | ||
} | ||
}; | ||
Object.defineProperty(ApplicationShell.prototype, "mode", { | ||
/** | ||
* The main dock area's user interface mode. | ||
*/ | ||
get: function () { | ||
return this._dockPanel.mode; | ||
}, | ||
set: function (mode) { | ||
var _this = this; | ||
var dock = this._dockPanel; | ||
if (mode === dock.mode) { | ||
return; | ||
} | ||
if (mode === 'single-document') { | ||
this._cachedLayout = dock.saveLayout(); | ||
dock.mode = mode; | ||
// In case the active widget in the dock panel is *not* the active widget | ||
// of the application, defer to the application. | ||
dock.activateWidget(this.currentWidget); | ||
// Set the mode data attribute on the document body. | ||
document.body.setAttribute(MODE_ATTRIBUTE, mode); | ||
return; | ||
} | ||
// Cache a reference to every widget currently in the dock panel. | ||
var widgets = algorithm_1.toArray(dock.widgets()); | ||
// Toggle back to multiple document mode. | ||
dock.mode = mode; | ||
// Restore the original layout. | ||
if (this._cachedLayout) { | ||
// Remove any disposed widgets in the cached layout and restore. | ||
Private.normalizeAreaConfig(dock, this._cachedLayout.main); | ||
dock.restoreLayout(this._cachedLayout); | ||
this._cachedLayout = null; | ||
} | ||
// Add any widgets created during single document mode, which have | ||
// subsequently been removed from the dock panel after the multiple document | ||
// layout has been restored. | ||
widgets.forEach(function (widget) { | ||
if (!widget.parent) { | ||
_this.addToMainArea(widget); | ||
} | ||
}); | ||
// In case the active widget in the dock panel is *not* the active widget | ||
// of the application, defer to the application. | ||
dock.activateWidget(this.currentWidget); | ||
// Set the mode data attribute on the document body. | ||
document.body.setAttribute(MODE_ATTRIBUTE, mode); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(ApplicationShell.prototype, "restored", { | ||
@@ -177,3 +234,3 @@ /** | ||
/** | ||
* Activate a widget in it's area. | ||
* Activate a widget in its area. | ||
*/ | ||
@@ -213,3 +270,3 @@ ApplicationShell.prototype.activateById = function (id) { | ||
if (ci === current.titles.length - 1) { | ||
var nextBar = this._nextTabBar(); | ||
var nextBar = this._adjacentBar('next'); | ||
if (nextBar) { | ||
@@ -239,3 +296,3 @@ nextBar.currentIndex = 0; | ||
if (ci === 0) { | ||
var prevBar = this._previousTabBar(); | ||
var prevBar = this._adjacentBar('previous'); | ||
if (prevBar) { | ||
@@ -257,6 +314,6 @@ var len = prevBar.titles.length; | ||
if (!widget.id) { | ||
console.error('widgets added to app shell must have unique id property'); | ||
console.error('Widgets added to app shell must have unique id property.'); | ||
return; | ||
} | ||
var rank = 'rank' in options ? options.rank : 100; | ||
var rank = 'rank' in options ? options.rank : DEFAULT_RANK; | ||
this._leftHandler.addWidget(widget, rank); | ||
@@ -275,3 +332,3 @@ this._save(); | ||
if (!widget.id) { | ||
console.error('widgets added to app shell must have unique id property'); | ||
console.error('Widgets added to app shell must have unique id property.'); | ||
return; | ||
@@ -291,6 +348,6 @@ } | ||
if (!widget.id) { | ||
console.error('widgets added to app shell must have unique id property'); | ||
console.error('Widgets added to app shell must have unique id property.'); | ||
return; | ||
} | ||
var rank = 'rank' in options ? options.rank : 100; | ||
var rank = 'rank' in options ? options.rank : DEFAULT_RANK; | ||
this._rightHandler.addWidget(widget, rank); | ||
@@ -308,3 +365,3 @@ this._save(); | ||
if (!widget.id) { | ||
console.error('widgets added to app shell must have unique id property'); | ||
console.error('Widgets added to app shell must have unique id property.'); | ||
return; | ||
@@ -340,2 +397,19 @@ } | ||
/** | ||
* True if the given area is empty. | ||
*/ | ||
ApplicationShell.prototype.isEmpty = function (area) { | ||
switch (area) { | ||
case 'left': | ||
return this._leftHandler.stackedPanel.widgets.length === 0; | ||
case 'main': | ||
return this._dockPanel.isEmpty; | ||
case 'top': | ||
return this._topPanel.widgets.length === 0; | ||
case 'right': | ||
return this._rightHandler.stackedPanel.widgets.length === 0; | ||
default: | ||
return true; | ||
} | ||
}; | ||
/** | ||
* Set the layout data store for the application shell. | ||
@@ -356,8 +430,12 @@ */ | ||
if (mainArea) { | ||
if (mainArea.dock) { | ||
_this._dockPanel.restoreLayout(mainArea.dock); | ||
var currentWidget = mainArea.currentWidget, dock = mainArea.dock, mode = mainArea.mode; | ||
if (dock) { | ||
_this._dockPanel.restoreLayout(dock); | ||
} | ||
if (mainArea.currentWidget) { | ||
_this.activateById(mainArea.currentWidget.id); | ||
if (mode) { | ||
_this.mode = mode; | ||
} | ||
if (currentWidget) { | ||
_this.activateById(currentWidget.id); | ||
} | ||
} | ||
@@ -387,21 +465,31 @@ // Rehydrate the left area. | ||
}; | ||
/* | ||
* Return the TabBar that has the currently active Widget or null. | ||
/** | ||
* Returns the widgets for an application area. | ||
*/ | ||
ApplicationShell.prototype._currentTabBar = function () { | ||
var current = this._tracker.currentWidget; | ||
if (!current) { | ||
return null; | ||
ApplicationShell.prototype.widgets = function (area) { | ||
switch (area) { | ||
case 'main': | ||
return this._dockPanel.widgets(); | ||
case 'left': | ||
return algorithm_1.iter(this._leftHandler.sideBar.titles.map(function (t) { return t.owner; })); | ||
case 'right': | ||
return algorithm_1.iter(this._rightHandler.sideBar.titles.map(function (t) { return t.owner; })); | ||
case 'top': | ||
return this._topPanel.children(); | ||
default: | ||
break; | ||
} | ||
var title = current.title; | ||
return algorithm_1.find(this._dockPanel.tabBars(), function (bar) { | ||
return algorithm_1.ArrayExt.firstIndexOf(bar.titles, title) > -1; | ||
}) || null; | ||
}; | ||
/** | ||
* Handle `after-attach` messages for the application shell. | ||
*/ | ||
ApplicationShell.prototype.onAfterAttach = function (msg) { | ||
document.body.setAttribute(MODE_ATTRIBUTE, this.mode); | ||
}; | ||
/* | ||
* Return the TabBar previous to the current TabBar (see above) or null. | ||
* Return the tab bar adjacent to the current TabBar or `null`. | ||
*/ | ||
ApplicationShell.prototype._previousTabBar = function () { | ||
ApplicationShell.prototype._adjacentBar = function (direction) { | ||
var current = this._currentTabBar(); | ||
if (current) { | ||
if (!current) { | ||
return null; | ||
@@ -411,46 +499,36 @@ } | ||
var len = bars.length; | ||
var ci = algorithm_1.ArrayExt.firstIndexOf(bars, current); | ||
if (ci > 0) { | ||
return bars[ci - 1]; | ||
var index = bars.indexOf(current); | ||
if (direction === 'previous') { | ||
return index > 0 ? bars[index - 1] | ||
: index === 0 ? bars[len - 1] | ||
: null; | ||
} | ||
if (ci === 0) { | ||
return bars[len - 1]; | ||
} | ||
return null; | ||
// Otherwise, direction is 'next'. | ||
return index < len - 1 ? bars[index + 1] | ||
: index === len - 1 ? bars[0] | ||
: null; | ||
}; | ||
/* | ||
* Return the TabBar next to the current TabBar (see above) or null. | ||
* Return the TabBar that has the currently active Widget or null. | ||
*/ | ||
ApplicationShell.prototype._nextTabBar = function () { | ||
var current = this._currentTabBar(); | ||
ApplicationShell.prototype._currentTabBar = function () { | ||
var current = this._tracker.currentWidget; | ||
if (!current) { | ||
return null; | ||
} | ||
var bars = algorithm_1.toArray(this._dockPanel.tabBars()); | ||
var len = bars.length; | ||
var ci = algorithm_1.ArrayExt.firstIndexOf(bars, current); | ||
if (ci < (len - 1)) { | ||
return bars[ci + 1]; | ||
} | ||
if (ci === len - 1) { | ||
return bars[0]; | ||
} | ||
return null; | ||
var title = current.title; | ||
var bars = this._dockPanel.tabBars(); | ||
return algorithm_1.find(bars, function (bar) { return bar.titles.indexOf(title) > -1; }) || null; | ||
}; | ||
/** | ||
* Save the dehydrated state of the application shell. | ||
* Handle a change to the dock area active widget. | ||
*/ | ||
ApplicationShell.prototype._save = function () { | ||
if (!this._database || !this._isRestored) { | ||
return; | ||
ApplicationShell.prototype._onActiveChanged = function (sender, args) { | ||
if (args.newValue) { | ||
args.newValue.title.className += " " + ACTIVE_CLASS; | ||
} | ||
var data = { | ||
mainArea: { | ||
currentWidget: this._tracker.currentWidget, | ||
dock: this._dockPanel.saveLayout() | ||
}, | ||
leftArea: this._leftHandler.dehydrate(), | ||
rightArea: this._rightHandler.dehydrate() | ||
}; | ||
return this._database.save(data); | ||
if (args.oldValue) { | ||
args.oldValue.title.className = (args.oldValue.title.className.replace(ACTIVE_CLASS, '')); | ||
} | ||
this._activeChanged.emit(args); | ||
}; | ||
@@ -470,12 +548,22 @@ /** | ||
/** | ||
* Handle a change to the dock area active widget. | ||
* Save the dehydrated state of the application shell. | ||
*/ | ||
ApplicationShell.prototype._onActiveChanged = function (sender, args) { | ||
if (args.newValue) { | ||
args.newValue.title.className += " " + ACTIVE_CLASS; | ||
ApplicationShell.prototype._save = function () { | ||
if (!this._database || !this._isRestored) { | ||
return; | ||
} | ||
if (args.oldValue) { | ||
args.oldValue.title.className = (args.oldValue.title.className.replace(ACTIVE_CLASS, '')); | ||
} | ||
this._activeChanged.emit(args); | ||
// If the application is in single document mode, use the cached layout if | ||
// available. Otherwise, default to querying the dock panel for layout. | ||
var data = { | ||
mainArea: { | ||
currentWidget: this._tracker.currentWidget, | ||
dock: this.mode === 'single-document' ? | ||
this._cachedLayout || this._dockPanel.saveLayout() | ||
: this._dockPanel.saveLayout(), | ||
mode: this._dockPanel.mode | ||
}, | ||
leftArea: this._leftHandler.dehydrate(), | ||
rightArea: this._rightHandler.dehydrate() | ||
}; | ||
return this._database.save(data); | ||
}; | ||
@@ -502,2 +590,14 @@ return ApplicationShell; | ||
/** | ||
* Removes widgets that have been disposed from an area config, mutates area. | ||
*/ | ||
function normalizeAreaConfig(parent, area) { | ||
if (area.type === 'tab-area') { | ||
area.widgets = area.widgets | ||
.filter(function (widget) { return !widget.isDisposed && widget.parent === parent; }); | ||
return; | ||
} | ||
area.children.forEach(function (child) { normalizeAreaConfig(parent, child); }); | ||
} | ||
Private.normalizeAreaConfig = normalizeAreaConfig; | ||
/** | ||
* A class which manages a side bar and related stacked panel. | ||
@@ -613,3 +713,3 @@ */ | ||
SideBarHandler.prototype._findWidgetIndex = function (widget) { | ||
return algorithm_1.ArrayExt.findFirstIndex(this._items, function (item) { return item.widget === widget; }); | ||
return algorithm_1.ArrayExt.findFirstIndex(this._items, function (i) { return i.widget === widget; }); | ||
}; | ||
@@ -650,6 +750,7 @@ /** | ||
if (newWidget) { | ||
document.body.setAttribute("data-" + this._side + "Area", newWidget.id); | ||
var id = newWidget.id; | ||
document.body.setAttribute("data-" + this._side + "-sidebar-widget", id); | ||
} | ||
else { | ||
document.body.removeAttribute("data-" + this._side + "Area"); | ||
document.body.removeAttribute("data-" + this._side + "-sidebar-widget"); | ||
} | ||
@@ -656,0 +757,0 @@ this._refreshVisibility(); |
{ | ||
"name": "@jupyterlab/application", | ||
"version": "0.3.0", | ||
"version": "0.3.1", | ||
"description": "JupyterLab - Application", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
73870
2079