@lumino/widgets
Version:
Lumino Widgets
1,264 lines (1,254 loc) • 640 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@lumino/algorithm'), require('@lumino/domutils'), require('@lumino/messaging'), require('@lumino/properties'), require('@lumino/signaling'), require('@lumino/dragdrop'), require('@lumino/coreutils'), require('@lumino/commands'), require('@lumino/virtualdom'), require('@lumino/disposable'), require('@lumino/keyboard')) :
typeof define === 'function' && define.amd ? define(['exports', '@lumino/algorithm', '@lumino/domutils', '@lumino/messaging', '@lumino/properties', '@lumino/signaling', '@lumino/dragdrop', '@lumino/coreutils', '@lumino/commands', '@lumino/virtualdom', '@lumino/disposable', '@lumino/keyboard'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.lumino_widgets = {}, global.lumino_algorithm, global.lumino_domutils, global.lumino_messaging, global.lumino_properties, global.lumino_signaling, global.lumino_dragdrop, global.lumino_coreutils, global.lumino_commands, global.lumino_virtualdom, global.lumino_disposable, global.lumino_keyboard));
}(this, (function (exports, algorithm, domutils, messaging, properties, signaling, dragdrop, coreutils, commands, virtualdom, disposable, keyboard) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
* A sizer object for use with the box engine layout functions.
*
* #### Notes
* A box sizer holds the geometry information for an object along an
* arbitrary layout orientation.
*
* For best performance, this class should be treated as a raw data
* struct. It should not typically be subclassed.
*/
var BoxSizer = /** @class */ (function () {
function BoxSizer() {
/**
* The preferred size for the sizer.
*
* #### Notes
* The sizer will be given this initial size subject to its size
* bounds. The sizer will not deviate from this size unless such
* deviation is required to fit into the available layout space.
*
* There is no limit to this value, but it will be clamped to the
* bounds defined by [[minSize]] and [[maxSize]].
*
* The default value is `0`.
*/
this.sizeHint = 0;
/**
* The minimum size of the sizer.
*
* #### Notes
* The sizer will never be sized less than this value, even if
* it means the sizer will overflow the available layout space.
*
* It is assumed that this value lies in the range `[0, Infinity)`
* and that it is `<=` to [[maxSize]]. Failure to adhere to this
* constraint will yield undefined results.
*
* The default value is `0`.
*/
this.minSize = 0;
/**
* The maximum size of the sizer.
*
* #### Notes
* The sizer will never be sized greater than this value, even if
* it means the sizer will underflow the available layout space.
*
* It is assumed that this value lies in the range `[0, Infinity]`
* and that it is `>=` to [[minSize]]. Failure to adhere to this
* constraint will yield undefined results.
*
* The default value is `Infinity`.
*/
this.maxSize = Infinity;
/**
* The stretch factor for the sizer.
*
* #### Notes
* This controls how much the sizer stretches relative to its sibling
* sizers when layout space is distributed. A stretch factor of zero
* is special and will cause the sizer to only be resized after all
* other sizers with a stretch factor greater than zero have been
* resized to their limits.
*
* It is assumed that this value is an integer that lies in the range
* `[0, Infinity)`. Failure to adhere to this constraint will yield
* undefined results.
*
* The default value is `1`.
*/
this.stretch = 1;
/**
* The computed size of the sizer.
*
* #### Notes
* This value is the output of a call to [[boxCalc]]. It represents
* the computed size for the object along the layout orientation,
* and will always lie in the range `[minSize, maxSize]`.
*
* This value is output only.
*
* Changing this value will have no effect.
*/
this.size = 0;
/**
* An internal storage property for the layout algorithm.
*
* #### Notes
* This value is used as temporary storage by the layout algorithm.
*
* Changing this value will have no effect.
*/
this.done = false;
}
return BoxSizer;
}());
/**
* The namespace for the box engine layout functions.
*/
exports.BoxEngine = void 0;
(function (BoxEngine) {
/**
* Calculate the optimal layout sizes for a sequence of box sizers.
*
* This distributes the available layout space among the box sizers
* according to the following algorithm:
*
* 1. Initialize the sizers's size to its size hint and compute the
* sums for each of size hint, min size, and max size.
*
* 2. If the total size hint equals the available space, return.
*
* 3. If the available space is less than the total min size, set all
* sizers to their min size and return.
*
* 4. If the available space is greater than the total max size, set
* all sizers to their max size and return.
*
* 5. If the layout space is less than the total size hint, distribute
* the negative delta as follows:
*
* a. Shrink each sizer with a stretch factor greater than zero by
* an amount proportional to the negative space and the sum of
* stretch factors. If the sizer reaches its min size, remove
* it and its stretch factor from the computation.
*
* b. If after adjusting all stretch sizers there remains negative
* space, distribute the space equally among the sizers with a
* stretch factor of zero. If a sizer reaches its min size,
* remove it from the computation.
*
* 6. If the layout space is greater than the total size hint,
* distribute the positive delta as follows:
*
* a. Expand each sizer with a stretch factor greater than zero by
* an amount proportional to the postive space and the sum of
* stretch factors. If the sizer reaches its max size, remove
* it and its stretch factor from the computation.
*
* b. If after adjusting all stretch sizers there remains positive
* space, distribute the space equally among the sizers with a
* stretch factor of zero. If a sizer reaches its max size,
* remove it from the computation.
*
* 7. return
*
* @param sizers - The sizers for a particular layout line.
*
* @param space - The available layout space for the sizers.
*
* @returns The delta between the provided available space and the
* actual consumed space. This value will be zero if the sizers
* can be adjusted to fit, negative if the available space is too
* small, and positive if the available space is too large.
*
* #### Notes
* The [[size]] of each sizer is updated with the computed size.
*
* This function can be called at any time to recompute the layout for
* an existing sequence of sizers. The previously computed results will
* have no effect on the new output. It is therefore not necessary to
* create new sizer objects on each resize event.
*/
function calc(sizers, space) {
// Bail early if there is nothing to do.
var count = sizers.length;
if (count === 0) {
return space;
}
// Setup the size and stretch counters.
var totalMin = 0;
var totalMax = 0;
var totalSize = 0;
var totalStretch = 0;
var stretchCount = 0;
// Setup the sizers and compute the totals.
for (var i = 0; i < count; ++i) {
var sizer = sizers[i];
var min = sizer.minSize;
var max = sizer.maxSize;
var hint = sizer.sizeHint;
sizer.done = false;
sizer.size = Math.max(min, Math.min(hint, max));
totalSize += sizer.size;
totalMin += min;
totalMax += max;
if (sizer.stretch > 0) {
totalStretch += sizer.stretch;
stretchCount++;
}
}
// If the space is equal to the total size, return early.
if (space === totalSize) {
return 0;
}
// If the space is less than the total min, minimize each sizer.
if (space <= totalMin) {
for (var i = 0; i < count; ++i) {
var sizer = sizers[i];
sizer.size = sizer.minSize;
}
return space - totalMin;
}
// If the space is greater than the total max, maximize each sizer.
if (space >= totalMax) {
for (var i = 0; i < count; ++i) {
var sizer = sizers[i];
sizer.size = sizer.maxSize;
}
return space - totalMax;
}
// The loops below perform sub-pixel precision sizing. A near zero
// value is used for compares instead of zero to ensure that the
// loop terminates when the subdivided space is reasonably small.
var nearZero = 0.01;
// A counter which is decremented each time a sizer is resized to
// its limit. This ensures the loops terminate even if there is
// space remaining to distribute.
var notDoneCount = count;
// Distribute negative delta space.
if (space < totalSize) {
// Shrink each stretchable sizer by an amount proportional to its
// stretch factor. If a sizer reaches its min size it's marked as
// done. The loop progresses in phases where each sizer is given
// a chance to consume its fair share for the pass, regardless of
// whether a sizer before it reached its limit. This continues
// until the stretchable sizers or the free space is exhausted.
var freeSpace = totalSize - space;
while (stretchCount > 0 && freeSpace > nearZero) {
var distSpace = freeSpace;
var distStretch = totalStretch;
for (var i = 0; i < count; ++i) {
var sizer = sizers[i];
if (sizer.done || sizer.stretch === 0) {
continue;
}
var amt = (sizer.stretch * distSpace) / distStretch;
if (sizer.size - amt <= sizer.minSize) {
freeSpace -= sizer.size - sizer.minSize;
totalStretch -= sizer.stretch;
sizer.size = sizer.minSize;
sizer.done = true;
notDoneCount--;
stretchCount--;
}
else {
freeSpace -= amt;
sizer.size -= amt;
}
}
}
// Distribute any remaining space evenly among the non-stretchable
// sizers. This progresses in phases in the same manner as above.
while (notDoneCount > 0 && freeSpace > nearZero) {
var amt = freeSpace / notDoneCount;
for (var i = 0; i < count; ++i) {
var sizer = sizers[i];
if (sizer.done) {
continue;
}
if (sizer.size - amt <= sizer.minSize) {
freeSpace -= sizer.size - sizer.minSize;
sizer.size = sizer.minSize;
sizer.done = true;
notDoneCount--;
}
else {
freeSpace -= amt;
sizer.size -= amt;
}
}
}
}
// Distribute positive delta space.
else {
// Expand each stretchable sizer by an amount proportional to its
// stretch factor. If a sizer reaches its max size it's marked as
// done. The loop progresses in phases where each sizer is given
// a chance to consume its fair share for the pass, regardless of
// whether a sizer before it reached its limit. This continues
// until the stretchable sizers or the free space is exhausted.
var freeSpace = space - totalSize;
while (stretchCount > 0 && freeSpace > nearZero) {
var distSpace = freeSpace;
var distStretch = totalStretch;
for (var i = 0; i < count; ++i) {
var sizer = sizers[i];
if (sizer.done || sizer.stretch === 0) {
continue;
}
var amt = (sizer.stretch * distSpace) / distStretch;
if (sizer.size + amt >= sizer.maxSize) {
freeSpace -= sizer.maxSize - sizer.size;
totalStretch -= sizer.stretch;
sizer.size = sizer.maxSize;
sizer.done = true;
notDoneCount--;
stretchCount--;
}
else {
freeSpace -= amt;
sizer.size += amt;
}
}
}
// Distribute any remaining space evenly among the non-stretchable
// sizers. This progresses in phases in the same manner as above.
while (notDoneCount > 0 && freeSpace > nearZero) {
var amt = freeSpace / notDoneCount;
for (var i = 0; i < count; ++i) {
var sizer = sizers[i];
if (sizer.done) {
continue;
}
if (sizer.size + amt >= sizer.maxSize) {
freeSpace -= sizer.maxSize - sizer.size;
sizer.size = sizer.maxSize;
sizer.done = true;
notDoneCount--;
}
else {
freeSpace -= amt;
sizer.size += amt;
}
}
}
}
// Indicate that the consumed space equals the available space.
return 0;
}
BoxEngine.calc = calc;
/**
* Adjust a sizer by a delta and update its neighbors accordingly.
*
* @param sizers - The sizers which should be adjusted.
*
* @param index - The index of the sizer to grow.
*
* @param delta - The amount to adjust the sizer, positive or negative.
*
* #### Notes
* This will adjust the indicated sizer by the specified amount, along
* with the sizes of the appropriate neighbors, subject to the limits
* specified by each of the sizers.
*
* This is useful when implementing box layouts where the boundaries
* between the sizers are interactively adjustable by the user.
*/
function adjust(sizers, index, delta) {
// Bail early when there is nothing to do.
if (sizers.length === 0 || delta === 0) {
return;
}
// Dispatch to the proper implementation.
if (delta > 0) {
growSizer(sizers, index, delta);
}
else {
shrinkSizer(sizers, index, -delta);
}
}
BoxEngine.adjust = adjust;
/**
* Grow a sizer by a positive delta and adjust neighbors.
*/
function growSizer(sizers, index, delta) {
// Compute how much the items to the left can expand.
var growLimit = 0;
for (var i = 0; i <= index; ++i) {
var sizer = sizers[i];
growLimit += sizer.maxSize - sizer.size;
}
// Compute how much the items to the right can shrink.
var shrinkLimit = 0;
for (var i = index + 1, n = sizers.length; i < n; ++i) {
var sizer = sizers[i];
shrinkLimit += sizer.size - sizer.minSize;
}
// Clamp the delta adjustment to the limits.
delta = Math.min(delta, growLimit, shrinkLimit);
// Grow the sizers to the left by the delta.
var grow = delta;
for (var i = index; i >= 0 && grow > 0; --i) {
var sizer = sizers[i];
var limit = sizer.maxSize - sizer.size;
if (limit >= grow) {
sizer.sizeHint = sizer.size + grow;
grow = 0;
}
else {
sizer.sizeHint = sizer.size + limit;
grow -= limit;
}
}
// Shrink the sizers to the right by the delta.
var shrink = delta;
for (var i = index + 1, n = sizers.length; i < n && shrink > 0; ++i) {
var sizer = sizers[i];
var limit = sizer.size - sizer.minSize;
if (limit >= shrink) {
sizer.sizeHint = sizer.size - shrink;
shrink = 0;
}
else {
sizer.sizeHint = sizer.size - limit;
shrink -= limit;
}
}
}
/**
* Shrink a sizer by a positive delta and adjust neighbors.
*/
function shrinkSizer(sizers, index, delta) {
// Compute how much the items to the right can expand.
var growLimit = 0;
for (var i = index + 1, n = sizers.length; i < n; ++i) {
var sizer = sizers[i];
growLimit += sizer.maxSize - sizer.size;
}
// Compute how much the items to the left can shrink.
var shrinkLimit = 0;
for (var i = 0; i <= index; ++i) {
var sizer = sizers[i];
shrinkLimit += sizer.size - sizer.minSize;
}
// Clamp the delta adjustment to the limits.
delta = Math.min(delta, growLimit, shrinkLimit);
// Grow the sizers to the right by the delta.
var grow = delta;
for (var i = index + 1, n = sizers.length; i < n && grow > 0; ++i) {
var sizer = sizers[i];
var limit = sizer.maxSize - sizer.size;
if (limit >= grow) {
sizer.sizeHint = sizer.size + grow;
grow = 0;
}
else {
sizer.sizeHint = sizer.size + limit;
grow -= limit;
}
}
// Shrink the sizers to the left by the delta.
var shrink = delta;
for (var i = index; i >= 0 && shrink > 0; --i) {
var sizer = sizers[i];
var limit = sizer.size - sizer.minSize;
if (limit >= shrink) {
sizer.sizeHint = sizer.size - shrink;
shrink = 0;
}
else {
sizer.sizeHint = sizer.size - limit;
shrink -= limit;
}
}
}
})(exports.BoxEngine || (exports.BoxEngine = {}));
// Copyright (c) Jupyter Development Team.
/**
* An object which holds data related to an object's title.
*
* #### Notes
* A title object is intended to hold the data necessary to display a
* header for a particular object. A common example is the `TabPanel`,
* which uses the widget title to populate the tab for a child widget.
*/
var Title = /** @class */ (function () {
/**
* Construct a new title.
*
* @param options - The options for initializing the title.
*/
function Title(options) {
this._label = '';
this._caption = '';
this._mnemonic = -1;
this._iconClass = '';
this._iconLabel = '';
this._className = '';
this._closable = false;
this._changed = new signaling.Signal(this);
this.owner = options.owner;
if (options.label !== undefined) {
this._label = options.label;
}
if (options.mnemonic !== undefined) {
this._mnemonic = options.mnemonic;
}
if (options.icon !== undefined) {
/* <DEPRECATED> */
if (typeof options.icon === 'string') {
// when ._icon is null, the .icon getter will alias .iconClass
this._icon = null;
this._iconClass = options.icon;
}
else {
/* </DEPRECATED> */
this._icon = options.icon;
/* <DEPRECATED> */
}
/* </DEPRECATED> */
}
else {
/* <DEPRECATED> */
// if unset, default to aliasing .iconClass
this._icon = null;
}
/* </DEPRECATED> */
if (options.iconClass !== undefined) {
this._iconClass = options.iconClass;
}
if (options.iconLabel !== undefined) {
this._iconLabel = options.iconLabel;
}
if (options.iconRenderer !== undefined) {
this._icon = options.iconRenderer;
}
if (options.caption !== undefined) {
this._caption = options.caption;
}
if (options.className !== undefined) {
this._className = options.className;
}
if (options.closable !== undefined) {
this._closable = options.closable;
}
this._dataset = options.dataset || {};
}
Object.defineProperty(Title.prototype, "changed", {
/**
* A signal emitted when the state of the title changes.
*/
get: function () {
return this._changed;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Title.prototype, "label", {
/**
* Get the label for the title.
*
* #### Notes
* The default value is an empty string.
*/
get: function () {
return this._label;
},
/**
* Set the label for the title.
*/
set: function (value) {
if (this._label === value) {
return;
}
this._label = value;
this._changed.emit(undefined);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Title.prototype, "mnemonic", {
/**
* Get the mnemonic index for the title.
*
* #### Notes
* The default value is `-1`.
*/
get: function () {
return this._mnemonic;
},
/**
* Set the mnemonic index for the title.
*/
set: function (value) {
if (this._mnemonic === value) {
return;
}
this._mnemonic = value;
this._changed.emit(undefined);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Title.prototype, "icon", {
/**
* Get the icon renderer for the title.
*
* #### Notes
* The default value is undefined.
*
* DEPRECATED: if set to a string value, the .icon field will function as
* an alias for the .iconClass field, for backwards compatibility
*/
get: function () {
/* <DEPRECATED> */
if (this._icon === null) {
// only alias .iconClass if ._icon has been explicitly nulled
return this.iconClass;
}
/* </DEPRECATED> */
return this._icon;
},
/**
* Set the icon renderer for the title.
*
* #### Notes
* A renderer is an object that supplies a render and unrender function.
*
* DEPRECATED: if set to a string value, the .icon field will function as
* an alias for the .iconClass field, for backwards compatibility
*/
set: function (value /* </DEPRECATED> */) {
/* <DEPRECATED> */
if (typeof value === 'string') {
// when ._icon is null, the .icon getter will alias .iconClass
this._icon = null;
this.iconClass = value;
}
else {
/* </DEPRECATED> */
if (this._icon === value) {
return;
}
this._icon = value;
this._changed.emit(undefined);
/* <DEPRECATED> */
}
/* </DEPRECATED> */
},
enumerable: true,
configurable: true
});
Object.defineProperty(Title.prototype, "iconClass", {
/**
* Get the icon class name for the title.
*
* #### Notes
* The default value is an empty string.
*/
get: function () {
return this._iconClass;
},
/**
* Set the icon class name for the title.
*
* #### Notes
* Multiple class names can be separated with whitespace.
*/
set: function (value) {
if (this._iconClass === value) {
return;
}
this._iconClass = value;
this._changed.emit(undefined);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Title.prototype, "iconLabel", {
/**
* Get the icon label for the title.
*
* #### Notes
* The default value is an empty string.
*/
get: function () {
return this._iconLabel;
},
/**
* Set the icon label for the title.
*
* #### Notes
* Multiple class names can be separated with whitespace.
*/
set: function (value) {
if (this._iconLabel === value) {
return;
}
this._iconLabel = value;
this._changed.emit(undefined);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Title.prototype, "iconRenderer", {
/**
* @deprecated Use `icon` instead.
*/
get: function () {
return this._icon || undefined;
},
/**
* @deprecated Use `icon` instead.
*/
set: function (value) {
this.icon = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Title.prototype, "caption", {
/**
* Get the caption for the title.
*
* #### Notes
* The default value is an empty string.
*/
get: function () {
return this._caption;
},
/**
* Set the caption for the title.
*/
set: function (value) {
if (this._caption === value) {
return;
}
this._caption = value;
this._changed.emit(undefined);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Title.prototype, "className", {
/**
* Get the extra class name for the title.
*
* #### Notes
* The default value is an empty string.
*/
get: function () {
return this._className;
},
/**
* Set the extra class name for the title.
*
* #### Notes
* Multiple class names can be separated with whitespace.
*/
set: function (value) {
if (this._className === value) {
return;
}
this._className = value;
this._changed.emit(undefined);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Title.prototype, "closable", {
/**
* Get the closable state for the title.
*
* #### Notes
* The default value is `false`.
*/
get: function () {
return this._closable;
},
/**
* Set the closable state for the title.
*
* #### Notes
* This controls the presence of a close icon when applicable.
*/
set: function (value) {
if (this._closable === value) {
return;
}
this._closable = value;
this._changed.emit(undefined);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Title.prototype, "dataset", {
/**
* Get the dataset for the title.
*
* #### Notes
* The default value is an empty dataset.
*/
get: function () {
return this._dataset;
},
/**
* Set the dataset for the title.
*
* #### Notes
* This controls the data attributes when applicable.
*/
set: function (value) {
if (this._dataset === value) {
return;
}
this._dataset = value;
this._changed.emit(undefined);
},
enumerable: true,
configurable: true
});
return Title;
}());
/**
* The base class of the lumino widget hierarchy.
*
* #### Notes
* This class will typically be subclassed in order to create a useful
* widget. However, it can be used directly to host externally created
* content.
*/
exports.Widget = /** @class */ (function () {
/**
* Construct a new widget.
*
* @param options - The options for initializing the widget.
*/
function Widget(options) {
if (options === void 0) { options = {}; }
this._flags = 0;
this._layout = null;
this._parent = null;
this._disposed = new signaling.Signal(this);
this._hiddenMode = Widget.HiddenMode.Display;
this.node = Private$j.createNode(options);
this.addClass('lm-Widget');
/* <DEPRECATED> */
this.addClass('p-Widget');
/* </DEPRECATED> */
}
/**
* Dispose of the widget and its descendant widgets.
*
* #### Notes
* It is unsafe to use the widget after it has been disposed.
*
* All calls made to this method after the first are a no-op.
*/
Widget.prototype.dispose = function () {
// Do nothing if the widget is already disposed.
if (this.isDisposed) {
return;
}
// Set the disposed flag and emit the disposed signal.
this.setFlag(Widget.Flag.IsDisposed);
this._disposed.emit(undefined);
// Remove or detach the widget if necessary.
if (this.parent) {
this.parent = null;
}
else if (this.isAttached) {
Widget.detach(this);
}
// Dispose of the widget layout.
if (this._layout) {
this._layout.dispose();
this._layout = null;
}
// Clear the extra data associated with the widget.
signaling.Signal.clearData(this);
messaging.MessageLoop.clearData(this);
properties.AttachedProperty.clearData(this);
};
Object.defineProperty(Widget.prototype, "disposed", {
/**
* A signal emitted when the widget is disposed.
*/
get: function () {
return this._disposed;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Widget.prototype, "isDisposed", {
/**
* Test whether the widget has been disposed.
*/
get: function () {
return this.testFlag(Widget.Flag.IsDisposed);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Widget.prototype, "isAttached", {
/**
* Test whether the widget's node is attached to the DOM.
*/
get: function () {
return this.testFlag(Widget.Flag.IsAttached);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Widget.prototype, "isHidden", {
/**
* Test whether the widget is explicitly hidden.
*/
get: function () {
return this.testFlag(Widget.Flag.IsHidden);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Widget.prototype, "isVisible", {
/**
* Test whether the widget is visible.
*
* #### Notes
* A widget is visible when it is attached to the DOM, is not
* explicitly hidden, and has no explicitly hidden ancestors.
*/
get: function () {
return this.testFlag(Widget.Flag.IsVisible);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Widget.prototype, "title", {
/**
* The title object for the widget.
*
* #### Notes
* The title object is used by some container widgets when displaying
* the widget alongside some title, such as a tab panel or side bar.
*
* Since not all widgets will use the title, it is created on demand.
*
* The `owner` property of the title is set to this widget.
*/
get: function () {
return Private$j.titleProperty.get(this);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Widget.prototype, "id", {
/**
* Get the id of the widget's DOM node.
*/
get: function () {
return this.node.id;
},
/**
* Set the id of the widget's DOM node.
*/
set: function (value) {
this.node.id = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Widget.prototype, "dataset", {
/**
* The dataset for the widget's DOM node.
*/
get: function () {
return this.node.dataset;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Widget.prototype, "hiddenMode", {
/**
* Get the method for hiding the widget.
*/
get: function () {
return this._hiddenMode;
},
/**
* Set the method for hiding the widget.
*/
set: function (value) {
if (this._hiddenMode === value) {
return;
}
this._hiddenMode = value;
switch (value) {
case Widget.HiddenMode.Display:
this.node.style.willChange = 'auto';
break;
case Widget.HiddenMode.Scale:
this.node.style.willChange = 'transform';
break;
}
if (this.isHidden) {
if (value === Widget.HiddenMode.Display) {
this.addClass('lm-mod-hidden');
/* <DEPRECATED> */
this.addClass('p-mod-hidden');
/* </DEPRECATED> */
this.node.style.transform = '';
}
else {
this.node.style.transform = 'scale(0)';
this.removeClass('lm-mod-hidden');
/* <DEPRECATED> */
this.removeClass('p-mod-hidden');
/* </DEPRECATED> */
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(Widget.prototype, "parent", {
/**
* Get the parent of the widget.
*/
get: function () {
return this._parent;
},
/**
* Set the parent of the widget.
*
* #### Notes
* Children are typically added to a widget by using a layout, which
* means user code will not normally set the parent widget directly.
*
* The widget will be automatically removed from its old parent.
*
* This is a no-op if there is no effective parent change.
*/
set: function (value) {
if (this._parent === value) {
return;
}
if (value && this.contains(value)) {
throw new Error('Invalid parent widget.');
}
if (this._parent && !this._parent.isDisposed) {
var msg = new Widget.ChildMessage('child-removed', this);
messaging.MessageLoop.sendMessage(this._parent, msg);
}
this._parent = value;
if (this._parent && !this._parent.isDisposed) {
var msg = new Widget.ChildMessage('child-added', this);
messaging.MessageLoop.sendMessage(this._parent, msg);
}
if (!this.isDisposed) {
messaging.MessageLoop.sendMessage(this, Widget.Msg.ParentChanged);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(Widget.prototype, "layout", {
/**
* Get the layout for the widget.
*/
get: function () {
return this._layout;
},
/**
* Set the layout for the widget.
*
* #### Notes
* The layout is single-use only. It cannot be changed after the
* first assignment.
*
* The layout is disposed automatically when the widget is disposed.
*/
set: function (value) {
if (this._layout === value) {
return;
}
if (this.testFlag(Widget.Flag.DisallowLayout)) {
throw new Error('Cannot set widget layout.');
}
if (this._layout) {
throw new Error('Cannot change widget layout.');
}
if (value.parent) {
throw new Error('Cannot change layout parent.');
}
this._layout = value;
value.parent = this;
},
enumerable: true,
configurable: true
});
/**
* Create an iterator over the widget's children.
*
* @returns A new iterator over the children of the widget.
*
* #### Notes
* The widget must have a populated layout in order to have children.
*
* If a layout is not installed, the returned iterator will be empty.
*/
Widget.prototype.children = function () {
return this._layout ? this._layout.iter() : algorithm.empty();
};
/**
* Test whether a widget is a descendant of this widget.
*
* @param widget - The descendant widget of interest.
*
* @returns `true` if the widget is a descendant, `false` otherwise.
*/
Widget.prototype.contains = function (widget) {
for (var value = widget; value; value = value._parent) {
if (value === this) {
return true;
}
}
return false;
};
/**
* Test whether the widget's DOM node has the given class name.
*
* @param name - The class name of interest.
*
* @returns `true` if the node has the class, `false` otherwise.
*/
Widget.prototype.hasClass = function (name) {
return this.node.classList.contains(name);
};
/**
* Add a class name to the widget's DOM node.
*
* @param name - The class name to add to the node.
*
* #### Notes
* If the class name is already added to the node, this is a no-op.
*
* The class name must not contain whitespace.
*/
Widget.prototype.addClass = function (name) {
this.node.classList.add(name);
};
/**
* Remove a class name from the widget's DOM node.
*
* @param name - The class name to remove from the node.
*
* #### Notes
* If the class name is not yet added to the node, this is a no-op.
*
* The class name must not contain whitespace.
*/
Widget.prototype.removeClass = function (name) {
this.node.classList.remove(name);
};
/**
* Toggle a class name on the widget's DOM node.
*
* @param name - The class name to toggle on the node.
*
* @param force - Whether to force add the class (`true`) or force
* remove the class (`false`). If not provided, the presence of
* the class will be toggled from its current state.
*
* @returns `true` if the class is now present, `false` otherwise.
*
* #### Notes
* The class name must not contain whitespace.
*/
Widget.prototype.toggleClass = function (name, force) {
if (force === true) {
this.node.classList.add(name);
return true;
}
if (force === false) {
this.node.classList.remove(name);
return false;
}
return this.node.classList.toggle(name);
};
/**
* Post an `'update-request'` message to the widget.
*
* #### Notes
* This is a simple convenience method for posting the message.
*/
Widget.prototype.update = function () {
messaging.MessageLoop.postMessage(this, Widget.Msg.UpdateRequest);
};
/**
* Post a `'fit-request'` message to the widget.
*
* #### Notes
* This is a simple convenience method for posting the message.
*/
Widget.prototype.fit = function () {
messaging.MessageLoop.postMessage(this, Widget.Msg.FitRequest);
};
/**
* Post an `'activate-request'` message to the widget.
*
* #### Notes
* This is a