Merge pull request #285 from mathuo/284-layouting

feat: retain layout size after fromJSON
This commit is contained in:
mathuo 2023-06-21 20:00:57 +01:00 committed by GitHub
commit b77df7c168
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 598 additions and 26 deletions

View File

@ -541,6 +541,8 @@ describe('dockviewComponent', () => {
},
});
// dockview.layout(1000, 1000, true);
expect(JSON.parse(JSON.stringify(dockview.toJSON()))).toEqual({
activeGroup: 'group-1',
grid: {
@ -1723,6 +1725,9 @@ describe('dockviewComponent', () => {
test_tab_id: PanelTabPartTest,
},
});
dockview.layout(1000, 1000);
dockview.fromJSON({
activeGroup: 'group-1',
grid: {
@ -1918,6 +1923,8 @@ describe('dockviewComponent', () => {
orientation: Orientation.HORIZONTAL,
});
dockview.layout(1000, 1000);
expect(dockview.orientation).toBe(Orientation.HORIZONTAL);
dockview.fromJSON({
@ -2023,6 +2030,8 @@ describe('dockviewComponent', () => {
orientation: Orientation.HORIZONTAL,
});
dockview.layout(1000, 1000);
expect(dockview.orientation).toBe(Orientation.HORIZONTAL);
dockview.fromJSON({
@ -2163,6 +2172,8 @@ describe('dockviewComponent', () => {
orientation: Orientation.HORIZONTAL,
});
dockview.layout(1000, 1000);
expect(dockview.orientation).toBe(Orientation.HORIZONTAL);
dockview.fromJSON({
@ -2517,4 +2528,95 @@ describe('dockviewComponent', () => {
expect(dockview.element.querySelectorAll('.view').length).toBe(2);
});
test('that fromJSON layouts are resized to the current dimensions', async () => {
const container = document.createElement('div');
const dockview = new DockviewComponent({
parentElement: container,
components: {
default: PanelContentPartTest,
},
tabComponents: {
test_tab_id: PanelTabPartTest,
},
orientation: Orientation.HORIZONTAL,
});
expect(dockview.orientation).toBe(Orientation.HORIZONTAL);
dockview.layout(1000, 500);
dockview.fromJSON({
activeGroup: 'group-1',
grid: {
root: {
type: 'branch',
data: [
{
type: 'leaf',
data: {
views: ['panel1', 'panel2'],
id: 'group-1',
activeView: 'panel2',
},
size: 2000,
},
],
size: 1000,
},
height: 1000,
width: 2000,
orientation: Orientation.HORIZONTAL,
},
panels: {
panel1: {
id: 'panel1',
contentComponent: 'default',
title: 'panel1',
},
panel2: {
id: 'panel2',
contentComponent: 'default',
title: 'panel2',
},
},
});
expect(JSON.parse(JSON.stringify(dockview.toJSON()))).toEqual({
activeGroup: 'group-1',
grid: {
root: {
type: 'branch',
data: [
{
type: 'leaf',
data: {
views: ['panel1', 'panel2'],
id: 'group-1',
activeView: 'panel2',
},
size: 1000,
},
],
size: 500,
},
height: 500,
width: 1000,
orientation: Orientation.HORIZONTAL,
},
panels: {
panel1: {
id: 'panel1',
contentComponent: 'default',
title: 'panel1',
},
panel2: {
id: 'panel2',
contentComponent: 'default',
title: 'panel2',
},
},
});
});
});

View File

@ -471,6 +471,8 @@ describe('gridview', () => {
components: { default: TestGridview },
});
gridview.layout(800, 400);
gridview.fromJSON({
grid: {
height: 400,
@ -528,7 +530,8 @@ describe('gridview', () => {
components: { default: TestGridview },
});
// gridview.layout(800, 400);
gridview.layout(800, 400);
gridview.fromJSON({
grid: {
height: 400,
@ -552,7 +555,6 @@ describe('gridview', () => {
},
activePanel: 'panel_1',
});
// gridview.layout(800, 400, true);
expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({
grid: {
@ -587,7 +589,8 @@ describe('gridview', () => {
components: { default: TestGridview },
});
// gridview.layout(800, 400);
gridview.layout(800, 400);
gridview.fromJSON({
grid: {
height: 400,
@ -620,7 +623,6 @@ describe('gridview', () => {
},
activePanel: 'panel_1',
});
// gridview.layout(800, 400, true);
expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({
grid: {
@ -664,7 +666,8 @@ describe('gridview', () => {
components: { default: TestGridview },
});
// gridview.layout(800, 400);
gridview.layout(800, 400);
gridview.fromJSON({
grid: {
height: 400,
@ -706,7 +709,6 @@ describe('gridview', () => {
},
activePanel: 'panel_1',
});
// gridview.layout(800, 400, true);
expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({
grid: {
@ -759,7 +761,8 @@ describe('gridview', () => {
components: { default: TestGridview },
});
// gridview.layout(800, 400);
gridview.layout(800, 400);
gridview.fromJSON({
grid: {
height: 400,
@ -801,7 +804,6 @@ describe('gridview', () => {
},
activePanel: 'panel_1',
});
// gridview.layout(800, 400, true);
expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({
grid: {
@ -854,6 +856,8 @@ describe('gridview', () => {
components: { default: TestGridview },
});
gridview.layout(800, 400);
gridview.fromJSON({
grid: {
height: 400,
@ -895,7 +899,6 @@ describe('gridview', () => {
},
activePanel: 'panel_1',
});
gridview.layout(800, 400, true);
expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({
grid: {
@ -948,7 +951,8 @@ describe('gridview', () => {
components: { default: TestGridview },
});
// gridview.layout(800, 400);
gridview.layout(800, 400);
gridview.fromJSON({
grid: {
height: 400,
@ -1005,7 +1009,6 @@ describe('gridview', () => {
},
activePanel: 'panel_1',
});
// gridview.layout(800, 400, true);
expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({
grid: {
@ -1198,6 +1201,8 @@ describe('gridview', () => {
components: { default: TestGridview },
});
gridview.layout(800, 400);
gridview.fromJSON({
grid: {
height: 400,
@ -1254,7 +1259,8 @@ describe('gridview', () => {
},
activePanel: 'panel_1',
});
gridview.layout(800, 400, true);
// gridview.layout(800, 400, true);
expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({
grid: {
@ -1322,6 +1328,8 @@ describe('gridview', () => {
components: { default: TestGridview },
});
gridview.layout(800, 400);
gridview.fromJSON({
grid: {
height: 400,
@ -1445,6 +1453,8 @@ describe('gridview', () => {
components: { default: TestGridview },
});
gridview.layout(800, 400);
gridview.fromJSON({
grid: {
height: 400,
@ -1908,4 +1918,318 @@ describe('gridview', () => {
return disposable.dispose();
});
test('that fromJSON layouts are resized to the current dimensions', async () => {
const container = document.createElement('div');
const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true,
orientation: Orientation.VERTICAL,
components: { default: TestGridview },
});
gridview.layout(1600, 800);
gridview.fromJSON({
grid: {
height: 400,
width: 800,
orientation: Orientation.HORIZONTAL,
root: {
type: 'branch',
size: 400,
data: [
{
type: 'leaf',
size: 200,
data: {
id: 'panel_1',
component: 'default',
snap: false,
},
},
{
type: 'branch',
size: 400,
data: [
{
type: 'leaf',
size: 250,
data: {
id: 'panel_2',
component: 'default',
snap: false,
},
},
{
type: 'leaf',
size: 150,
data: {
id: 'panel_3',
component: 'default',
snap: false,
},
},
],
},
{
type: 'leaf',
size: 200,
data: {
id: 'panel_4',
component: 'default',
snap: false,
},
},
],
},
},
activePanel: 'panel_1',
});
expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({
grid: {
height: 800,
width: 1600,
orientation: Orientation.HORIZONTAL,
root: {
type: 'branch',
size: 800,
data: [
{
type: 'leaf',
size: 400,
data: {
id: 'panel_1',
component: 'default',
snap: false,
},
},
{
type: 'branch',
size: 800,
data: [
{
type: 'leaf',
size: 500,
data: {
id: 'panel_2',
component: 'default',
snap: false,
},
},
{
type: 'leaf',
size: 300,
data: {
id: 'panel_3',
component: 'default',
snap: false,
},
},
],
},
{
type: 'leaf',
size: 400,
data: {
id: 'panel_4',
component: 'default',
snap: false,
},
},
],
},
},
activePanel: 'panel_1',
});
});
test('that a deep layout with fromJSON dimensions identical to the current dimensions loads', async () => {
const container = document.createElement('div');
const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true,
orientation: Orientation.VERTICAL,
components: { default: TestGridview },
});
gridview.layout(5000, 5000);
gridview.fromJSON({
grid: {
height: 5000,
width: 5000,
orientation: Orientation.HORIZONTAL,
root: {
type: 'branch',
size: 5000,
data: [
{
type: 'leaf',
size: 1000,
data: {
id: 'panel_1',
component: 'default',
snap: false,
},
},
{
type: 'branch',
size: 2000,
data: [
{
type: 'branch',
size: 4000,
data: [
{
type: 'leaf',
size: 1000,
data: {
id: 'panel_2',
component: 'default',
snap: false,
},
},
{
type: 'branch',
size: 1000,
data: [
{
type: 'leaf',
size: 2000,
data: {
id: 'panel_3',
component: 'default',
snap: false,
},
},
{
type: 'leaf',
size: 2000,
data: {
id: 'panel_4',
component: 'default',
snap: false,
},
},
],
},
],
},
{
type: 'leaf',
size: 1000,
data: {
id: 'panel_5',
component: 'default',
snap: false,
},
},
],
},
{
type: 'leaf',
size: 2000,
data: {
id: 'panel_6',
component: 'default',
snap: false,
},
},
],
},
},
activePanel: 'panel_1',
});
expect(JSON.parse(JSON.stringify(gridview.toJSON()))).toEqual({
grid: {
height: 5000,
width: 5000,
orientation: Orientation.HORIZONTAL,
root: {
type: 'branch',
size: 5000,
data: [
{
type: 'leaf',
size: 1000,
data: {
id: 'panel_1',
component: 'default',
snap: false,
},
},
{
type: 'branch',
size: 2000,
data: [
{
type: 'branch',
size: 4000,
data: [
{
type: 'leaf',
size: 1000,
data: {
id: 'panel_2',
component: 'default',
snap: false,
},
},
{
type: 'branch',
size: 1000,
data: [
{
type: 'leaf',
size: 2000,
data: {
id: 'panel_3',
component: 'default',
snap: false,
},
},
{
type: 'leaf',
size: 2000,
data: {
id: 'panel_4',
component: 'default',
snap: false,
},
},
],
},
],
},
{
type: 'leaf',
size: 1000,
data: {
id: 'panel_5',
component: 'default',
snap: false,
},
},
],
},
{
type: 'leaf',
size: 2000,
data: {
id: 'panel_6',
component: 'default',
snap: false,
},
},
],
},
},
activePanel: 'panel_1',
});
});
});

View File

@ -408,4 +408,85 @@ describe('componentPaneview', () => {
expect(panel1Spy).toHaveBeenCalledTimes(1);
expect(panel2Spy).toHaveBeenCalledTimes(1);
});
test('that fromJSON layouts are resized to the current dimensions', async () => {
const paneview = new PaneviewComponent({
parentElement: container,
components: {
testPanel: TestPanel,
},
});
paneview.layout(400, 600);
paneview.fromJSON({
size: 6,
views: [
{
size: 1,
data: {
id: 'panel1',
component: 'testPanel',
title: 'Panel 1',
},
expanded: true,
},
{
size: 2,
data: {
id: 'panel2',
component: 'testPanel',
title: 'Panel 2',
},
expanded: true,
},
{
size: 3,
data: {
id: 'panel3',
component: 'testPanel',
title: 'Panel 3',
},
expanded: true,
},
],
});
// heights slightly differ because header height isn't accounted for
expect(JSON.parse(JSON.stringify(paneview.toJSON()))).toEqual({
size: 600,
views: [
{
size: 122,
data: {
id: 'panel1',
component: 'testPanel',
title: 'Panel 1',
},
expanded: true,
minimumSize: 100,
},
{
size: 122,
data: {
id: 'panel2',
component: 'testPanel',
title: 'Panel 2',
},
expanded: true,
minimumSize: 100,
},
{
size: 356,
data: {
id: 'panel3',
component: 'testPanel',
title: 'Panel 3',
},
expanded: true,
minimumSize: 100,
},
],
});
});
});

View File

@ -330,7 +330,7 @@ describe('componentSplitview', () => {
testPanel: TestPanel,
},
});
splitview.layout(600, 400);
splitview.layout(400, 6);
splitview.fromJSON({
views: [
@ -535,4 +535,57 @@ describe('componentSplitview', () => {
expect(panel1Spy).toHaveBeenCalledTimes(1);
expect(panel2Spy).toHaveBeenCalledTimes(1);
});
test('that fromJSON layouts are resized to the current dimensions', async () => {
const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.VERTICAL,
components: {
testPanel: TestPanel,
},
});
splitview.layout(400, 600);
splitview.fromJSON({
views: [
{
size: 1,
data: { id: 'panel1', component: 'testPanel' },
snap: false,
},
{
size: 2,
data: { id: 'panel2', component: 'testPanel' },
snap: true,
},
{ size: 3, data: { id: 'panel3', component: 'testPanel' } },
],
size: 6,
orientation: Orientation.VERTICAL,
activeView: 'panel1',
});
expect(JSON.parse(JSON.stringify(splitview.toJSON()))).toEqual({
views: [
{
size: 100,
data: { id: 'panel1', component: 'testPanel' },
snap: false,
},
{
size: 200,
data: { id: 'panel2', component: 'testPanel' },
snap: true,
},
{
size: 300,
data: { id: 'panel3', component: 'testPanel' },
snap: false,
},
],
size: 600,
orientation: Orientation.VERTICAL,
activeView: 'panel1',
});
});
});

View File

@ -412,6 +412,10 @@ export class DockviewComponent
throw new Error('root must be of type branch');
}
// take note of the existing dimensions
const width = this.width;
const height = this.height;
this.gridview.deserialize(grid, {
fromJSON: (node: ISerializedLeafNode<GroupPanelViewState>) => {
const { id, locked, hideHeader, views, activeView } = node.data;
@ -453,6 +457,8 @@ export class DockviewComponent
},
});
this.layout(width, height);
if (typeof activeGroup === 'string') {
const panel = this.getPanel(activeGroup);
if (panel) {
@ -460,8 +466,6 @@ export class DockviewComponent
}
}
this.gridview.layout(this.width, this.height);
this._onDidLayoutFromJSON.fire();
}

View File

@ -371,8 +371,7 @@ export class Gridview implements IDisposable {
root,
orientation,
deserializer,
orthogonalSize,
true
orthogonalSize
) as BranchNode;
}
@ -380,8 +379,7 @@ export class Gridview implements IDisposable {
node: ISerializedNode,
orientation: Orientation,
deserializer: IViewDeserializer,
orthogonalSize: number,
isRoot = false
orthogonalSize: number
): Node {
let result: Node;
if (node.type === 'branch') {
@ -398,14 +396,12 @@ export class Gridview implements IDisposable {
} as INodeDescriptor;
});
// HORIZONTAL => height=orthogonalsize width=size
// VERTICAL => height=size width=orthogonalsize
result = new BranchNode(
orientation,
this.proportionalLayout,
this.styles,
isRoot ? orthogonalSize : node.size,
isRoot ? node.size : orthogonalSize,
orthogonalSize, // <- size - flips at each depth
node.size, // <- orthogonal size - flips at each depth
children
);
} else {

View File

@ -176,6 +176,10 @@ export class GridviewComponent
const queue: Function[] = [];
// take note of the existing dimensions
const width = this.width;
const height = this.height;
this.gridview.deserialize(grid, {
fromJSON: (node) => {
const { data } = node;
@ -215,7 +219,7 @@ export class GridviewComponent
},
});
this.layout(this.width, this.height, true);
this.layout(width, height);
queue.forEach((f) => f());

View File

@ -360,6 +360,10 @@ export class PaneviewComponent extends Resizable implements IPaneviewComponent {
const queue: Function[] = [];
// take note of the existing dimensions
const width = this.width;
const height = this.height;
this.paneview = new Paneview(this.element, {
orientation: Orientation.VERTICAL,
descriptor: {
@ -437,7 +441,7 @@ export class PaneviewComponent extends Resizable implements IPaneviewComponent {
},
});
this.layout(this.width, this.height);
this.layout(width, height);
queue.forEach((f) => f());

View File

@ -337,6 +337,10 @@ export class SplitviewComponent
const queue: Function[] = [];
// take note of the existing dimensions
const width = this.width;
const height = this.height;
this.splitview = new Splitview(this.element, {
orientation,
proportionalLayout: this.options.proportionalLayout,
@ -387,7 +391,7 @@ export class SplitviewComponent
},
});
this.layout(this.width, this.height);
this.layout(width, height);
queue.forEach((f) => f());