diff --git a/packages/dockview-core/src/__tests__/splitview/splitview.spec.ts b/packages/dockview-core/src/__tests__/splitview/splitview.spec.ts index 631fa0407..e659b9d9d 100644 --- a/packages/dockview-core/src/__tests__/splitview/splitview.spec.ts +++ b/packages/dockview-core/src/__tests__/splitview/splitview.spec.ts @@ -782,8 +782,9 @@ describe('splitview', () => { splitview.layout(924, 500); const view1 = new Testview(0, 1000); - const view2 = new Testview(0, 1000, LayoutPriority.High); + const view2 = new Testview(0, 1000); const view3 = new Testview(0, 1000); + const view4 = new Testview(0, 1000); splitview.addView(view1); expect([view1.size]).toEqual([924]); @@ -793,5 +794,108 @@ describe('splitview', () => { splitview.addView(view3); expect([view1.size, view2.size, view3.size]).toEqual([292, 292, 292]); // 292 + 24 + 292 + 24 + 292 = 924 + + splitview.addView(view4); + expect([view1.size, view2.size, view3.size, view4.size]).toEqual([ + 213, 213, 213, 213, + ]); // 213 + 24 + 213 + 24 + 213 + 24 + 213 = 924 + + let viewQuery = Array.from( + container + .querySelectorAll( + '.split-view-container > .view-container > .view' + ) + .entries() + ) + .map(([i, e]) => e as HTMLElement) + .map((e) => ({ + left: e.style.left, + top: e.style.top, + height: e.style.height, + width: e.style.width, + })); + + let sashQuery = Array.from( + container + .querySelectorAll( + '.split-view-container > .sash-container > .sash' + ) + .entries() + ) + .map(([i, e]) => e as HTMLElement) + .map((e) => ({ + left: e.style.left, + top: e.style.top, + })); + + // check HTMLElement positions since these are the ones that really matter + + expect(viewQuery).toEqual([ + { left: '0px', top: '', width: '213px', height: '' }, + // 213 + 24 = 237 + { left: '237px', top: '', width: '213px', height: '' }, + // 237 + 213 + 24 = 474 + { left: '474px', top: '', width: '213px', height: '' }, + // 474 + 213 + 24 = 474 + { left: '711px', top: '', width: '213px', height: '' }, + // 711 + 213 = 924 + ]); + + // 924 / 4 = 231 view size + // 231 - (24*3/4) = 213 margin adjusted view size + // 213 - 4/2 + 24/2 = 223 + expect(sashQuery).toEqual([ + // 213 - 4/2 + 24/2 = 223 + { left: '223px', top: '0px' }, + // 213 + 24 + 213 = 450 + // 450 - 4/2 + 24/2 = 460 + { left: '460px', top: '0px' }, + // 213 + 24 + 213 + 24 + 213 = 687 + // 687 - 4/2 + 24/2 = 697 + { left: '697px', top: '0px' }, + ]); + + splitview.setViewVisible(0, false); + + viewQuery = Array.from( + container + .querySelectorAll( + '.split-view-container > .view-container > .view' + ) + .entries() + ) + .map(([i, e]) => e as HTMLElement) + .map((e) => ({ + left: e.style.left, + top: e.style.top, + height: e.style.height, + width: e.style.width, + })); + + sashQuery = Array.from( + container + .querySelectorAll( + '.split-view-container > .sash-container > .sash' + ) + .entries() + ) + .map(([i, e]) => e as HTMLElement) + .map((e) => ({ + left: e.style.left, + top: e.style.top, + })); + + expect(viewQuery).toEqual([ + { left: '0px', top: '', width: '0px', height: '' }, + { left: '0px', top: '', width: '215px', height: '' }, + { left: '239px', top: '', width: '215px', height: '' }, + { left: '478px', top: '', width: '446px', height: '' }, + ]); + + expect(sashQuery).toEqual([ + { left: '0px', top: '0px' }, + { left: '225px', top: '0px' }, + { left: '464px', top: '0px' }, + ]); }); }); diff --git a/packages/dockview-core/src/splitview/splitview.ts b/packages/dockview-core/src/splitview/splitview.ts index 6fd1c2f28..268a17e40 100644 --- a/packages/dockview-core/src/splitview/splitview.ts +++ b/packages/dockview-core/src/splitview/splitview.ts @@ -811,43 +811,69 @@ export class Splitview { return; } - const sashCount = this.viewItems.length - 1; + const visibleViewItems = this.viewItems.filter((i) => i.visible); + + const sashCount = Math.max(0, visibleViewItems.length - 1); const marginReducedSize = - (this.margin * sashCount) / this.viewItems.length; + (this.margin * sashCount) / Math.max(1, visibleViewItems.length); let totalLeftOffset = 0; const viewLeftOffsets: number[] = []; - for (let i = 0; i < this.viewItems.length - 1; i++) { + const sashWidth = 4; // hardcoded in css + + const runningVisiblePanelCount = this.viewItems.reduce( + (arr, viewItem, i) => { + const flag = viewItem.visible ? 1 : 0; + if (i === 0) { + arr.push(flag); + } else { + arr.push(arr[i - 1] + flag); + } + + return arr; + }, + [] as number[] + ); + + // calculate both view and cash positions + this.viewItems.forEach((view, i) => { totalLeftOffset += this.viewItems[i].size; viewLeftOffsets.push(totalLeftOffset); - const offset = Math.min( - Math.max(0, totalLeftOffset - 2), - this.size - this.margin - ); + const size = view.visible ? view.size - marginReducedSize : 0; + + const visiblePanelsBeforeThisView = Math.max(0, runningVisiblePanelCount[i] - 1); - if (this._orientation === Orientation.HORIZONTAL) { - this.sashes[i].container.style.left = `${offset}px`; - this.sashes[i].container.style.top = `0px`; - } - if (this._orientation === Orientation.VERTICAL) { - this.sashes[i].container.style.left = `0px`; - this.sashes[i].container.style.top = `${offset}px`; - } - } - this.viewItems.forEach((view, i) => { - const size = view.size - marginReducedSize; const offset = - i === 0 + i === 0 || visiblePanelsBeforeThisView === 0 ? 0 : viewLeftOffsets[i - 1] + - (i / sashCount) * marginReducedSize; + (visiblePanelsBeforeThisView / sashCount) * marginReducedSize; + + if (i < this.viewItems.length - 1) { + // calculate sash position + const newSize = view.visible + ? offset + size - sashWidth / 2 + this.margin / 2 + : offset; + + if (this._orientation === Orientation.HORIZONTAL) { + this.sashes[i].container.style.left = `${newSize}px`; + this.sashes[i].container.style.top = `0px`; + } + if (this._orientation === Orientation.VERTICAL) { + this.sashes[i].container.style.left = `0px`; + this.sashes[i].container.style.top = `${newSize}px`; + } + } + + // calculate view position if (this._orientation === Orientation.HORIZONTAL) { view.container.style.width = `${size}px`; view.container.style.left = `${offset}px`; view.container.style.top = ''; + view.container.style.height = ''; } if (this._orientation === Orientation.VERTICAL) { diff --git a/packages/dockview-core/src/theme.scss b/packages/dockview-core/src/theme.scss index 47cfab4ce..96c259d5f 100644 --- a/packages/dockview-core/src/theme.scss +++ b/packages/dockview-core/src/theme.scss @@ -268,6 +268,8 @@ } .vertical > .sash-container > .sash { + + &:not(.disabled) { &::after { content: ''; height: 4px; @@ -287,9 +289,11 @@ ); } } + } } .horizontal > .sash-container > .sash { + &:not(.disabled) { &::after { content: ''; height: 40px; @@ -309,6 +313,7 @@ ); } } + } } }