UNPKG

jupyterlab-emrys

Version:

A computational environment for Jupyter. Powered by Emrys

230 lines (229 loc) 8 kB
// Copyright (c) Jupyter Development Team. // Distributed under the terms of the Modified BSD License. "use strict"; var phosphor_disposable_1 = require('phosphor-disposable'); var phosphor_messaging_1 = require('phosphor-messaging'); var phosphor_properties_1 = require('phosphor-properties'); var dialog_1 = require('../dialog'); /** * The class name added to document widgets. */ var DOCUMENT_CLASS = 'jp-Document'; /** * A class that maintains the lifecyle of file-backed widgets. */ var DocumentWidgetManager = (function () { /** * Construct a new document widget manager. */ function DocumentWidgetManager(options) { this._closeGuard = false; this._contextManager = null; this._registry = null; this._widgets = Object.create(null); this._contextManager = options.contextManager; this._registry = options.registry; } /** * Dispose of the resources used by the widget manager. */ DocumentWidgetManager.prototype.dispose = function () { this._registry = null; this._contextManager = null; for (var id in this._widgets) { for (var _i = 0, _a = this._widgets[id]; _i < _a.length; _i++) { var widget = _a[_i]; widget.dispose(); } } }; /** * Create a widget for a document and handle its lifecycle. */ DocumentWidgetManager.prototype.createWidget = function (name, id, kernel) { var factory = this._registry.getWidgetFactory(name); var context = this._contextManager.getContext(id); var widget = factory.createNew(context, kernel); Private.nameProperty.set(widget, name); // Handle widget extensions. var disposables = new phosphor_disposable_1.DisposableSet(); for (var _i = 0, _a = this._registry.getWidgetExtensions(name); _i < _a.length; _i++) { var extender = _a[_i]; disposables.add(extender.createNew(widget, context)); } widget.disposed.connect(function () { disposables.dispose(); }); this.adoptWidget(id, widget); return widget; }; /** * Install the message filter for the widget and add to list * of known widgets. */ DocumentWidgetManager.prototype.adoptWidget = function (id, widget) { var _this = this; if (!(id in this._widgets)) { this._widgets[id] = []; } this._widgets[id].push(widget); phosphor_messaging_1.installMessageFilter(widget, this); widget.addClass(DOCUMENT_CLASS); widget.title.closable = true; widget.disposed.connect(function () { // Remove the widget from the widget registry. var index = _this._widgets[id].indexOf(widget); _this._widgets[id].splice(index, 1); // Dispose of the context if this is the last widget using it. if (!_this._widgets[id].length) { _this._contextManager.removeContext(id); } }); Private.idProperty.set(widget, id); }; /** * See if a widget already exists for the given path and widget name. * * #### Notes * This can be used to use an existing widget instead of opening * a new widget. */ DocumentWidgetManager.prototype.findWidget = function (path, widgetName) { var ids = this._contextManager.getIdsForPath(path); for (var _i = 0, ids_1 = ids; _i < ids_1.length; _i++) { var id = ids_1[_i]; for (var _a = 0, _b = this._widgets[id]; _a < _b.length; _a++) { var widget = _b[_a]; var name_1 = Private.nameProperty.get(widget); if (name_1 === widgetName) { return widget; } } } }; /** * Get the document context for a widget. */ DocumentWidgetManager.prototype.contextForWidget = function (widget) { var id = Private.idProperty.get(widget); return this._contextManager.getContext(id); }; /** * Clone a widget. * * #### Notes * This will create a new widget with the same model and context * as this widget. */ DocumentWidgetManager.prototype.clone = function (widget) { var id = Private.idProperty.get(widget); var name = Private.nameProperty.get(widget); var newWidget = this.createWidget(name, id); this.adoptWidget(id, newWidget); return widget; }; /** * Close the widgets associated with a given path. */ DocumentWidgetManager.prototype.closeFile = function (path) { var ids = this._contextManager.getIdsForPath(path); for (var _i = 0, ids_2 = ids; _i < ids_2.length; _i++) { var id = ids_2[_i]; var widgets = this._widgets[id] || []; for (var _a = 0, widgets_1 = widgets; _a < widgets_1.length; _a++) { var w = widgets_1[_a]; w.close(); } } }; /** * Close all of the open documents. */ DocumentWidgetManager.prototype.closeAll = function () { for (var id in this._widgets) { for (var _i = 0, _a = this._widgets[id]; _i < _a.length; _i++) { var w = _a[_i]; w.close(); } } }; /** * Filter a message sent to a message handler. * * @param handler - The target handler of the message. * * @param msg - The message dispatched to the handler. * * @returns `true` if the message should be filtered, of `false` * if the message should be dispatched to the handler as normal. */ DocumentWidgetManager.prototype.filterMessage = function (handler, msg) { if (msg.type === 'close-request') { if (this._closeGuard) { return false; } this.onClose(handler); return true; } return false; }; /** * Handle `'close-request'` messages. */ DocumentWidgetManager.prototype.onClose = function (widget) { var _this = this; // Handle dirty state. this._maybeClose(widget).then(function (result) { if (result) { _this._closeGuard = true; widget.close(); _this._closeGuard = false; // Dispose of document widgets when they are closed. widget.dispose(); } }).catch(function () { widget.dispose(); }); }; /** * Ask the user whether to close an unsaved file. */ DocumentWidgetManager.prototype._maybeClose = function (widget) { // Bail if the model is not dirty or other widgets are using the model. var id = Private.idProperty.get(widget); var widgets = this._widgets[id]; var model = this._contextManager.getModel(id); if (!model.dirty || widgets.length > 1) { return Promise.resolve(true); } return dialog_1.showDialog({ title: 'Close without saving?', body: "File \"" + widget.title.text + "\" has unsaved changes, close without saving?" }).then(function (value) { if (value && value.text === 'OK') { return true; } return false; }); }; return DocumentWidgetManager; }()); exports.DocumentWidgetManager = DocumentWidgetManager; /** * A private namespace for DocumentManager data. */ var Private; (function (Private) { /** * A private attached property for a widget context id. */ Private.idProperty = new phosphor_properties_1.Property({ name: 'id' }); /** * A private attached property for a widget factory name. */ Private.nameProperty = new phosphor_properties_1.Property({ name: 'name' }); })(Private || (Private = {}));