dockview
Version:
Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support
248 lines (247 loc) • 9.65 kB
JavaScript
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());
}
}
}