UNPKG

dockview

Version:

Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support

478 lines 21.1 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Accreditation: This file is largly based upon the MIT licenced VSCode sourcecode found at: * https://github.com/microsoft/vscode/tree/main/src/vs/base/browser/ui/grid *--------------------------------------------------------------------------------------------*/ var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Gridview = exports.isGridBranchNode = exports.orthogonal = exports.getLocationOrientation = exports.getDirectionOrientation = exports.getRelativeLocation = exports.getGridLocation = exports.indexInParent = void 0; var splitview_1 = require("../splitview/core/splitview"); var droptarget_1 = require("../dnd/droptarget"); var array_1 = require("../array"); var leafNode_1 = require("./leafNode"); var branchNode_1 = require("./branchNode"); var events_1 = require("../events"); var lifecycle_1 = require("../lifecycle"); function flipNode(node, size, orthogonalSize) { if (node instanceof branchNode_1.BranchNode) { var result = new branchNode_1.BranchNode((0, exports.orthogonal)(node.orientation), node.proportionalLayout, node.styles, size, orthogonalSize); var totalSize = 0; for (var i = node.children.length - 1; i >= 0; i--) { var child = node.children[i]; var childSize = child instanceof branchNode_1.BranchNode ? child.orthogonalSize : child.size; var newSize = node.size === 0 ? 0 : Math.round((size * childSize) / node.size); totalSize += newSize; // The last view to add should adjust to rounding errors if (i === 0) { newSize += size - totalSize; } result.addChild(flipNode(child, orthogonalSize, newSize), newSize, 0, true); } return result; } else { return new leafNode_1.LeafNode(node.view, (0, exports.orthogonal)(node.orientation), orthogonalSize); } } function indexInParent(element) { var parentElement = element.parentElement; if (!parentElement) { throw new Error('Invalid grid element'); } var el = parentElement.firstElementChild; var index = 0; while (el !== element && el !== parentElement.lastElementChild && el) { el = el.nextElementSibling; index++; } return index; } exports.indexInParent = indexInParent; /** * Find the grid location of a specific DOM element by traversing the parent * chain and finding each child index on the way. * * This will break as soon as DOM structures of the Splitview or Gridview change. */ function getGridLocation(element) { var parentElement = element.parentElement; if (!parentElement) { throw new Error('Invalid grid element'); } if (/\bgrid-view\b/.test(parentElement.className)) { return []; } var index = indexInParent(parentElement); var ancestor = parentElement.parentElement.parentElement.parentElement; return __spreadArray(__spreadArray([], __read(getGridLocation(ancestor)), false), [index], false); } exports.getGridLocation = getGridLocation; function getRelativeLocation(rootOrientation, location, direction) { var orientation = getLocationOrientation(rootOrientation, location); var directionOrientation = getDirectionOrientation(direction); if (orientation === directionOrientation) { var _a = __read((0, array_1.tail)(location), 2), rest = _a[0], _index = _a[1]; var index = _index; if (direction === droptarget_1.Position.Right || direction === droptarget_1.Position.Bottom) { index += 1; } return __spreadArray(__spreadArray([], __read(rest), false), [index], false); } else { var index = direction === droptarget_1.Position.Right || direction === droptarget_1.Position.Bottom ? 1 : 0; return __spreadArray(__spreadArray([], __read(location), false), [index], false); } } exports.getRelativeLocation = getRelativeLocation; function getDirectionOrientation(direction) { return direction === droptarget_1.Position.Top || direction === droptarget_1.Position.Bottom ? splitview_1.Orientation.VERTICAL : splitview_1.Orientation.HORIZONTAL; } exports.getDirectionOrientation = getDirectionOrientation; function getLocationOrientation(rootOrientation, location) { return location.length % 2 === 0 ? (0, exports.orthogonal)(rootOrientation) : rootOrientation; } exports.getLocationOrientation = getLocationOrientation; var orthogonal = function (orientation) { return orientation === splitview_1.Orientation.HORIZONTAL ? splitview_1.Orientation.VERTICAL : splitview_1.Orientation.HORIZONTAL; }; exports.orthogonal = orthogonal; function isGridBranchNode(node) { return !!node.children; } exports.isGridBranchNode = isGridBranchNode; var serializeBranchNode = function (node, orientation) { var size = orientation === splitview_1.Orientation.VERTICAL ? node.box.width : node.box.height; if (!isGridBranchNode(node)) { if (typeof node.cachedVisibleSize === 'number') { return { type: 'leaf', data: node.view.toJSON(), size: node.cachedVisibleSize, visible: false, }; } return { type: 'leaf', data: node.view.toJSON(), size: size }; } return { type: 'branch', data: node.children.map(function (c) { return serializeBranchNode(c, (0, exports.orthogonal)(orientation)); }), size: size, }; }; var Gridview = /** @class */ (function () { function Gridview(proportionalLayout, styles, orientation) { this.proportionalLayout = proportionalLayout; this.styles = styles; this.disposable = new lifecycle_1.MutableDisposable(); this._onDidChange = new events_1.Emitter(); this.onDidChange = this._onDidChange.event; this.element = document.createElement('div'); this.element.className = 'grid-view'; this.root = new branchNode_1.BranchNode(orientation, proportionalLayout, styles, 0, 0); } Gridview.prototype.serialize = function () { var root = serializeBranchNode(this.getView(), this.orientation); return { root: root, width: this.width, height: this.height, orientation: this.orientation, }; }; Gridview.prototype.dispose = function () { this.disposable.dispose(); this._onDidChange.dispose(); this.root.dispose(); }; Gridview.prototype.clear = function () { var orientation = this.root.orientation; this.root = new branchNode_1.BranchNode(orientation, this.proportionalLayout, this.styles, this.root.size, this.root.orthogonalSize); }; Gridview.prototype.deserialize = function (json, deserializer) { var orientation = json.orientation; var height = json.height; this._deserialize(json.root, orientation, deserializer, height); }; Gridview.prototype._deserialize = function (root, orientation, deserializer, orthogonalSize) { this.root = this._deserializeNode(root, orientation, deserializer, orthogonalSize); }; Gridview.prototype._deserializeNode = function (node, orientation, deserializer, orthogonalSize) { var _this = this; var result; if (node.type === 'branch') { var serializedChildren = node.data; var children = serializedChildren.map(function (serializedChild) { return { node: _this._deserializeNode(serializedChild, (0, exports.orthogonal)(orientation), deserializer, node.size), visible: serializedChild.visible, }; }); result = new branchNode_1.BranchNode(orientation, this.proportionalLayout, this.styles, node.size, orthogonalSize, children); } else { result = new leafNode_1.LeafNode(deserializer.fromJSON(node), orientation, orthogonalSize, node.size); } return result; }; Object.defineProperty(Gridview.prototype, "orientation", { get: function () { return this.root.orientation; }, set: function (orientation) { if (this.root.orientation === orientation) { return; } var _a = this.root, size = _a.size, orthogonalSize = _a.orthogonalSize; this.root = flipNode(this.root, orthogonalSize, size); this.root.layout(size, orthogonalSize); }, enumerable: false, configurable: true }); Object.defineProperty(Gridview.prototype, "root", { get: function () { return this._root; }, set: function (root) { var _this = this; var oldRoot = this._root; if (oldRoot) { oldRoot.dispose(); this.element.removeChild(oldRoot.element); } this._root = root; this.element.appendChild(this._root.element); this.disposable.value = this._root.onDidChange(function (e) { _this._onDidChange.fire(e); }); }, enumerable: false, configurable: true }); Gridview.prototype.next = function (location) { return this.progmaticSelect(location); }; Gridview.prototype.previous = function (location) { return this.progmaticSelect(location, true); }; Gridview.prototype.getView = function (location) { var node = location ? this.getNode(location)[1] : this.root; return this._getViews(node, this.orientation); }; Gridview.prototype._getViews = function (node, orientation, cachedVisibleSize) { var box = { height: node.height, width: node.width }; if (node instanceof leafNode_1.LeafNode) { return { box: box, view: node.view, cachedVisibleSize: cachedVisibleSize }; } var children = []; for (var i = 0; i < node.children.length; i++) { var child = node.children[i]; var nodeCachedVisibleSize = node.getChildCachedVisibleSize(i); children.push(this._getViews(child, (0, exports.orthogonal)(orientation), nodeCachedVisibleSize)); } return { box: box, children: children }; }; Gridview.prototype.progmaticSelect = function (location, reverse) { if (reverse === void 0) { reverse = false; } var _a = __read(this.getNode(location), 2), path = _a[0], node = _a[1]; if (!(node instanceof leafNode_1.LeafNode)) { throw new Error('invalid location'); } var findLeaf = function (candiateNode, last) { if (candiateNode instanceof leafNode_1.LeafNode) { return candiateNode; } if (candiateNode instanceof branchNode_1.BranchNode) { return findLeaf(candiateNode.children[last ? candiateNode.children.length - 1 : 0], last); } throw new Error('invalid node'); }; for (var i = path.length - 1; i > -1; i--) { var n = path[i]; var l = location[i] || 0; var canProgressInCurrentLevel = reverse ? l - 1 > -1 : l + 1 < n.children.length; if (canProgressInCurrentLevel) { return findLeaf(n.children[reverse ? l - 1 : l + 1], reverse); } } return findLeaf(this.root, reverse); }; Object.defineProperty(Gridview.prototype, "width", { get: function () { return this.root.width; }, enumerable: false, configurable: true }); Object.defineProperty(Gridview.prototype, "height", { get: function () { return this.root.height; }, enumerable: false, configurable: true }); Object.defineProperty(Gridview.prototype, "minimumWidth", { get: function () { return this.root.minimumWidth; }, enumerable: false, configurable: true }); Object.defineProperty(Gridview.prototype, "minimumHeight", { get: function () { return this.root.minimumHeight; }, enumerable: false, configurable: true }); Object.defineProperty(Gridview.prototype, "maximumWidth", { get: function () { return this.root.maximumHeight; }, enumerable: false, configurable: true }); Object.defineProperty(Gridview.prototype, "maximumHeight", { get: function () { return this.root.maximumHeight; }, enumerable: false, configurable: true }); Gridview.prototype.isViewVisible = function (location) { var _a = __read((0, array_1.tail)(location), 2), rest = _a[0], index = _a[1]; var _b = __read(this.getNode(rest), 2), parent = _b[1]; if (!(parent instanceof branchNode_1.BranchNode)) { throw new Error('Invalid from location'); } return parent.isChildVisible(index); }; Gridview.prototype.setViewVisible = function (location, visible) { var _a = __read((0, array_1.tail)(location), 2), rest = _a[0], index = _a[1]; var _b = __read(this.getNode(rest), 2), parent = _b[1]; if (!(parent instanceof branchNode_1.BranchNode)) { throw new Error('Invalid from location'); } parent.setChildVisible(index, visible); }; Gridview.prototype.moveView = function (parentLocation, from, to) { var _a = __read(this.getNode(parentLocation), 2), parent = _a[1]; if (!(parent instanceof branchNode_1.BranchNode)) { throw new Error('Invalid location'); } parent.moveChild(from, to); }; Gridview.prototype.addView = function (view, size, location) { var _a = __read((0, array_1.tail)(location), 2), rest = _a[0], index = _a[1]; var _b = __read(this.getNode(rest), 2), pathToParent = _b[0], parent = _b[1]; if (parent instanceof branchNode_1.BranchNode) { var node = new leafNode_1.LeafNode(view, (0, exports.orthogonal)(parent.orientation), parent.orthogonalSize); parent.addChild(node, size, index); } else { var _c = __read(__spreadArray([], __read(pathToParent), false).reverse()), grandParent = _c[0], _ = _c.slice(1); var _d = __read(__spreadArray([], __read(rest), false).reverse()), parentIndex = _d[0], __ = _d.slice(1); var newSiblingSize = 0; var newSiblingCachedVisibleSize = grandParent.getChildCachedVisibleSize(parentIndex); if (typeof newSiblingCachedVisibleSize === 'number') { newSiblingSize = splitview_1.Sizing.Invisible(newSiblingCachedVisibleSize); } grandParent.removeChild(parentIndex); var newParent = new branchNode_1.BranchNode(parent.orientation, this.proportionalLayout, this.styles, parent.size, parent.orthogonalSize); grandParent.addChild(newParent, parent.size, parentIndex); var newSibling = new leafNode_1.LeafNode(parent.view, grandParent.orientation, parent.size); newParent.addChild(newSibling, newSiblingSize, 0); if (typeof size !== 'number' && size.type === 'split') { size = { type: 'split', index: 0 }; } var node = new leafNode_1.LeafNode(view, grandParent.orientation, parent.size); newParent.addChild(node, size, index); } }; Gridview.prototype.remove = function (view, sizing) { var location = getGridLocation(view.element); return this.removeView(location, sizing); }; Gridview.prototype.removeView = function (location, sizing) { var _a = __read((0, array_1.tail)(location), 2), rest = _a[0], index = _a[1]; var _b = __read(this.getNode(rest), 2), pathToParent = _b[0], parent = _b[1]; if (!(parent instanceof branchNode_1.BranchNode)) { throw new Error('Invalid location'); } var node = parent.children[index]; if (!(node instanceof leafNode_1.LeafNode)) { throw new Error('Invalid location'); } parent.removeChild(index, sizing); if (parent.children.length === 0) { // throw new Error('Invalid grid state'); return node.view; } if (parent.children.length > 1) { return node.view; } if (pathToParent.length === 0) { // parent is root var sibling_1 = parent.children[0]; if (sibling_1 instanceof leafNode_1.LeafNode) { return node.view; } // we must promote sibling to be the new root parent.removeChild(0, sizing); this.root = sibling_1; return node.view; } var _c = __read(__spreadArray([], __read(pathToParent), false).reverse()), grandParent = _c[0], _ = _c.slice(1); var _d = __read(__spreadArray([], __read(rest), false).reverse()), parentIndex = _d[0], __ = _d.slice(1); var sibling = parent.children[0]; var isSiblingVisible = parent.isChildVisible(0); parent.removeChild(0, sizing); var sizes = grandParent.children.map(function (size, i) { return grandParent.getChildSize(i); }); grandParent.removeChild(parentIndex, sizing); if (sibling instanceof branchNode_1.BranchNode) { sizes.splice.apply(sizes, __spreadArray([parentIndex, 1], __read(sibling.children.map(function (c) { return c.size; })), false)); for (var i = 0; i < sibling.children.length; i++) { var child = sibling.children[i]; grandParent.addChild(child, child.size, parentIndex + i); } } else { var newSibling = new leafNode_1.LeafNode(sibling.view, (0, exports.orthogonal)(sibling.orientation), sibling.size); var siblingSizing = isSiblingVisible ? sibling.orthogonalSize : splitview_1.Sizing.Invisible(sibling.orthogonalSize); grandParent.addChild(newSibling, siblingSizing, parentIndex); } for (var i = 0; i < sizes.length; i++) { grandParent.resizeChild(i, sizes[i]); } return node.view; }; Gridview.prototype.layout = function (width, height) { var _a = __read(this.root.orientation === splitview_1.Orientation.HORIZONTAL ? [height, width] : [width, height], 2), size = _a[0], orthogonalSize = _a[1]; this.root.layout(size, orthogonalSize); }; Gridview.prototype.getNode = function (location, node, path) { if (node === void 0) { node = this.root; } if (path === void 0) { path = []; } if (location.length === 0) { return [path, node]; } if (!(node instanceof branchNode_1.BranchNode)) { throw new Error('Invalid location'); } var _a = __read(location), index = _a[0], rest = _a.slice(1); if (index < 0 || index >= node.children.length) { throw new Error('Invalid location'); } var child = node.children[index]; path.push(node); return this.getNode(rest, child, path); }; return Gridview; }()); exports.Gridview = Gridview; //# sourceMappingURL=gridview.js.map