UNPKG

dockview

Version:

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

248 lines (247 loc) 9.65 kB
import { PaneviewApi } from '../api/component.api'; import { createComponent } from '../panel/componentFactory'; import { Emitter } from '../events'; import { CompositeDisposable, MutableDisposable, } from '../lifecycle'; import { Orientation, Sizing, } from '../splitview/core/splitview'; import { Paneview } from './paneview'; import { DraggablePaneviewPanel, } from './draggablePaneviewPanel'; import { DefaultHeader } from './defaultPaneviewHeader'; export class PaneFramework extends DraggablePaneviewPanel { constructor(options) { super(options.id, options.component, options.headerComponent, options.orientation, options.isExpanded, options.disableDnd); this.options = options; } getBodyComponent() { return this.options.body; } getHeaderComponent() { return this.options.header; } } export class PaneviewComponent extends CompositeDisposable { constructor(element, options) { super(); this.element = element; this._disposable = new MutableDisposable(); this._onDidLayoutChange = new Emitter(); this.onDidLayoutChange = this._onDidLayoutChange.event; this._onDidDrop = new Emitter(); this.onDidDrop = this._onDidDrop.event; this._options = options; if (!options.components) { options.components = {}; } if (!options.frameworkComponents) { options.frameworkComponents = {}; } this.paneview = new Paneview(this.element, { // only allow paneview in the vertical orientation for now orientation: Orientation.VERTICAL, }); this.addDisposables(this._disposable); } get onDidAddView() { return this._paneview.onDidAddView; } get onDidRemoveView() { return this._paneview.onDidRemoveView; } set paneview(value) { this._paneview = value; this._disposable.value = new CompositeDisposable(this.paneview.onDidChange(() => { this._onDidLayoutChange.fire(undefined); })); } get paneview() { return this._paneview; } get minimumSize() { return this.paneview.minimumSize; } get maximumSize() { return this.paneview.maximumSize; } get height() { return this.paneview.orientation === Orientation.HORIZONTAL ? this.paneview.orthogonalSize : this.paneview.size; } get width() { return this.paneview.orientation === Orientation.HORIZONTAL ? this.paneview.size : this.paneview.orthogonalSize; } get options() { return this._options; } focus() { // } updateOptions(options) { this._options = Object.assign(Object.assign({}, this.options), options); } addPanel(options) { const body = createComponent(options.id, options.component, this.options.components || {}, this.options.frameworkComponents || {}, this.options.frameworkWrapper ? { createComponent: this.options.frameworkWrapper.body.createComponent, } : undefined); let header; if (options.headerComponent) { header = createComponent(options.id, options.headerComponent, this.options.headerComponents || {}, this.options.headerframeworkComponents, this.options.frameworkWrapper ? { createComponent: this.options.frameworkWrapper.header .createComponent, } : undefined); } else { header = new DefaultHeader(); } const view = new PaneFramework({ id: options.id, component: options.component, headerComponent: options.headerComponent, header, body, orientation: Orientation.VERTICAL, isExpanded: !!options.isExpanded, disableDnd: !!this.options.disableDnd, }); const disposable = new CompositeDisposable(view.onDidDrop((event) => { this._onDidDrop.fire(event); })); const size = typeof options.size === 'number' ? options.size : Sizing.Distribute; const index = typeof options.index === 'number' ? options.index : undefined; view.init({ params: options.params || {}, minimumBodySize: options.minimumBodySize, maximumBodySize: options.maximumBodySize, isExpanded: options.isExpanded, title: options.title, containerApi: new PaneviewApi(this), }); this.paneview.addPane(view, size, index); view.orientation = this.paneview.orientation; return disposable; } getPanels() { return this.paneview.getPanes(); } removePanel(panel) { const views = this.getPanels(); const index = views.findIndex((_) => _ === panel); this.paneview.removePane(index); } movePanel(from, to) { this.paneview.moveView(from, to); } getPanel(id) { return this.getPanels().find((view) => view.id === id); } layout(width, height) { const [size, orthogonalSize] = this.paneview.orientation === Orientation.HORIZONTAL ? [width, height] : [height, width]; this.paneview.layout(size, orthogonalSize); } /** * 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); } toJSON() { const maximum = (value) => value === Number.MAX_SAFE_INTEGER || value === Number.POSITIVE_INFINITY ? undefined : value; const minimum = (value) => (value <= 0 ? undefined : value); const views = this.paneview .getPanes() .map((view, i) => { const size = this.paneview.getViewSize(i); return { size, data: view.toJSON(), minimumSize: minimum(view.minimumBodySize), maximumSize: maximum(view.maximumBodySize), expanded: view.isExpanded(), }; }); return { views, size: this.paneview.size, }; } fromJSON(serializedPaneview, deferComponentLayout) { const { views, size } = serializedPaneview; const queue = []; this.paneview.dispose(); this.paneview = new Paneview(this.element, { orientation: Orientation.VERTICAL, descriptor: { size, views: views.map((view) => { const data = view.data; const body = createComponent(data.id, data.component, this.options.components || {}, this.options.frameworkComponents || {}, this.options.frameworkWrapper ? { createComponent: this.options.frameworkWrapper.body .createComponent, } : undefined); let header; if (data.headerComponent) { header = createComponent(data.id, data.headerComponent, this.options.headerComponents || {}, this.options.headerframeworkComponents || {}, this.options.frameworkWrapper ? { createComponent: this.options.frameworkWrapper.header .createComponent, } : undefined); } else { header = new DefaultHeader(); } const panel = new PaneFramework({ id: data.id, component: data.component, headerComponent: data.headerComponent, header, body, orientation: Orientation.VERTICAL, isExpanded: !!view.expanded, disableDnd: !!this.options.disableDnd, }); panel.onDidDrop((event) => { this._onDidDrop.fire(event); }); queue.push(() => { panel.init({ params: data.params || {}, minimumBodySize: view.minimumSize, maximumBodySize: view.maximumSize, title: data.title, isExpanded: !!view.expanded, containerApi: new PaneviewApi(this), }); panel.orientation = this.paneview.orientation; }); return { size: view.size, view: panel }; }), }, }); this.layout(this.width, this.height); if (deferComponentLayout) { setTimeout(() => { queue.forEach((f) => f()); }, 0); } else { queue.forEach((f) => f()); } } }