UNPKG

dockview

Version:

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

225 lines (224 loc) 7.85 kB
import { Emitter } from '../events'; import { getGridLocation, Gridview } from './gridview'; import { Position } from '../dnd/droptarget'; import { CompositeDisposable } from '../lifecycle'; import { sequentialNumberGenerator } from '../math'; import { Sizing, } from '../splitview/core/splitview'; export var GroupChangeKind; (function (GroupChangeKind) { GroupChangeKind["ADD_PANEL"] = "ADD_PANEL"; GroupChangeKind["REMOVE_PANEL"] = "REMOVE_PANEL"; GroupChangeKind["PANEL_ACTIVE"] = "PANEL_ACTIVE"; // GroupChangeKind["GROUP_ACTIVE"] = "GROUP_ACTIVE"; GroupChangeKind["ADD_GROUP"] = "ADD_GROUP"; GroupChangeKind["REMOVE_GROUP"] = "REMOVE_GROUP"; // GroupChangeKind["LAYOUT_FROM_JSON"] = "LAYOUT_FROM_JSON"; GroupChangeKind["LAYOUT"] = "LAYOUT"; })(GroupChangeKind || (GroupChangeKind = {})); const nextLayoutId = sequentialNumberGenerator(); export function toTarget(direction) { switch (direction) { case 'left': return Position.Left; case 'right': return Position.Right; case 'above': return Position.Top; case 'below': return Position.Bottom; case 'within': default: return Position.Center; } } export class BaseGrid extends CompositeDisposable { constructor(_element, options) { super(); this._element = _element; this._id = nextLayoutId.next(); this._groups = new Map(); // this._onGridEvent = new Emitter(); this.onGridEvent = this._onGridEvent.event; this._onDidLayoutChange = new Emitter(); this.onDidLayoutChange = this._onDidLayoutChange.event; this.gridview = new Gridview(!!options.proportionalLayout, options.styles, options.orientation); this.element.appendChild(this.gridview.element); // TODO for some reason this is required before anything will layout correctly this.layout(0, 0, true); this.addDisposables(this.gridview.onDidChange(() => { this._onGridEvent.fire({ kind: GroupChangeKind.LAYOUT }); })); this.addDisposables((() => { /** * TODO Fix this relatively ugly 'merge and delay' */ let timer; return this.onGridEvent((event) => { if ([ GroupChangeKind.ADD_GROUP, GroupChangeKind.REMOVE_GROUP, GroupChangeKind.ADD_PANEL, GroupChangeKind.REMOVE_PANEL, GroupChangeKind.GROUP_ACTIVE, GroupChangeKind.PANEL_ACTIVE, GroupChangeKind.LAYOUT, ].includes(event.kind)) { if (timer) { clearTimeout(timer); } timer = setTimeout(() => { this._onDidLayoutChange.fire(); clearTimeout(timer); }); } }); })()); } get id() { return this._id; } get element() { return this._element; } get size() { return this._groups.size; } get groups() { return Array.from(this._groups.values()).map((_) => _.value); } get width() { return this.gridview.width; } get height() { return this.gridview.height; } get minimumHeight() { return this.gridview.minimumHeight; } get maximumHeight() { return this.gridview.maximumHeight; } get minimumWidth() { return this.gridview.minimumWidth; } get maximumWidth() { return this.gridview.maximumWidth; } get activeGroup() { return this._activeGroup; } setVisible(panel, visible) { this.gridview.setViewVisible(getGridLocation(panel.element), visible); this._onGridEvent.fire({ kind: GroupChangeKind.LAYOUT }); } isVisible(panel) { return this.gridview.isViewVisible(getGridLocation(panel.element)); } doAddGroup(group, location = [0], size) { this.gridview.addView(group, size !== null && size !== void 0 ? size : Sizing.Distribute, location); this._onGridEvent.fire({ kind: GroupChangeKind.ADD_GROUP }); this.doSetGroupActive(group); } doRemoveGroup(group, options) { if (!this._groups.has(group.id)) { throw new Error('invalid operation'); } const item = this._groups.get(group.id); const view = this.gridview.remove(group, Sizing.Distribute); if (item && !(options === null || options === void 0 ? void 0 : options.skipDispose)) { item.disposable.dispose(); this._groups.delete(group.id); } this._onGridEvent.fire({ kind: GroupChangeKind.REMOVE_GROUP }); if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) { const groups = Array.from(this._groups.values()); this.doSetGroupActive(groups.length > 0 ? groups[0].value : undefined); } return view; } getPanel(id) { var _a; return (_a = this._groups.get(id)) === null || _a === void 0 ? void 0 : _a.value; } doSetGroupActive(group, skipFocus) { if (this._activeGroup === group) { return; } if (this._activeGroup) { this._activeGroup.setActive(false); if (!skipFocus) { this._activeGroup.focus(); } } if (group) { group.setActive(true); if (!skipFocus) { group.focus(); } } this._activeGroup = group; this._onGridEvent.fire({ kind: GroupChangeKind.GROUP_ACTIVE, }); } removeGroup(group) { this.doRemoveGroup(group); } moveToNext(options) { var _a; if (!options) { options = {}; } if (!options.group) { if (!this.activeGroup) { return; } options.group = this.activeGroup; } const location = getGridLocation(options.group.element); const next = (_a = this.gridview.next(location)) === null || _a === void 0 ? void 0 : _a.view; this.doSetGroupActive(next); } moveToPrevious(options) { var _a; if (!options) { options = {}; } if (!options.group) { if (!this.activeGroup) { return; } options.group = this.activeGroup; } const location = getGridLocation(options.group.element); const next = (_a = this.gridview.previous(location)) === null || _a === void 0 ? void 0 : _a.view; this.doSetGroupActive(next); } layout(width, height, forceResize) { const different = forceResize || width !== this.width || height !== this.height; if (!different) { return; } this.element.style.height = `${height}px`; this.element.style.width = `${width}px`; this.gridview.layout(width, height); } /** * Resize the layout to fit the parent container */ resizeToFit() { if (!this.element.parentElement) { return; } const { width, height } = this.element.parentElement.getBoundingClientRect(); this.layout(width, height); } dispose() { super.dispose(); this._onGridEvent.dispose(); this.gridview.dispose(); } }