diff --git a/src/vs/base/browser/ui/splitview/splitview.ts b/src/vs/base/browser/ui/splitview/splitview.ts index eff34aab6e4ffc1d7f9fccc2e6f87f9fb59c5c14..0de80a6c7637a7e7b5e080ca669cd232e3e2f434 100644 --- a/src/vs/base/browser/ui/splitview/splitview.ts +++ b/src/vs/base/browser/ui/splitview/splitview.ts @@ -47,6 +47,7 @@ export interface IView { readonly maximumSize: number; readonly onDidChange: Event; readonly priority?: LayoutPriority; + readonly snapSize?: number; layout(size: number, orientation: Orientation): void; } @@ -351,7 +352,7 @@ export class SplitView extends Disposable { } else { for (let i = 0; i < this.viewItems.length; i++) { const item = this.viewItems[i]; - item.size = clamp(Math.round(this.proportions[i] * size), item.view.minimumSize, item.view.maximumSize); + item.size = SplitView.clamp(item, Math.round(this.proportions[i] * size)); } } @@ -443,7 +444,7 @@ export class SplitView extends Disposable { } size = typeof size === 'number' ? size : item.size; - size = clamp(size, item.view.minimumSize, item.view.maximumSize); + size = SplitView.clamp(item, size); if (this.inverseAltBehavior && index > 0) { // In this case, we want the view to grow or shrink both sides equally @@ -550,27 +551,29 @@ export class SplitView extends Disposable { const downItems = downIndexes.map(i => this.viewItems[i]); const downSizes = downIndexes.map(i => sizes[i]); - const minDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.minimumSize - sizes[i]), 0); + const minDeltaUp = upIndexes.reduce((r, i) => r + ((typeof this.viewItems[i].view.snapSize === 'number' ? 0 : this.viewItems[i].view.minimumSize) - sizes[i]), 0); const maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - sizes[i]), 0); - const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.minimumSize), 0); + const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - (typeof this.viewItems[i].view.snapSize === 'number' ? 0 : this.viewItems[i].view.minimumSize)), 0); const minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.maximumSize), 0); const minDelta = Math.max(minDeltaUp, minDeltaDown, overloadMinDelta); const maxDelta = Math.min(maxDeltaDown, maxDeltaUp, overloadMaxDelta); - delta = clamp(delta, minDelta, maxDelta); + const tentativeDelta = clamp(delta, minDelta, maxDelta); + let actualDelta = 0; - for (let i = 0, deltaUp = delta; i < upItems.length; i++) { + for (let i = 0, deltaUp = tentativeDelta; i < upItems.length; i++) { const item = upItems[i]; - const size = clamp(upSizes[i] + deltaUp, item.view.minimumSize, item.view.maximumSize); + const size = SplitView.clamp(item, upSizes[i] + deltaUp/* , upIndexes[i] === index */); const viewDelta = size - upSizes[i]; + actualDelta += viewDelta; deltaUp -= viewDelta; item.size = size; } - for (let i = 0, deltaDown = delta; i < downItems.length; i++) { + for (let i = 0, deltaDown = actualDelta; i < downItems.length; i++) { const item = downItems[i]; - const size = clamp(downSizes[i] - deltaDown, item.view.minimumSize, item.view.maximumSize); + const size = SplitView.clamp(item, downSizes[i] - deltaDown); const viewDelta = size - downSizes[i]; deltaDown += viewDelta; @@ -580,13 +583,24 @@ export class SplitView extends Disposable { return delta; } + private static clamp(item: IViewItem, size: number): number { + const result = clamp(size, item.view.minimumSize, item.view.maximumSize); + + if (typeof item.view.snapSize !== 'number' || size >= item.view.minimumSize) { + return result; + } + + const snapSize = Math.min(item.view.snapSize, item.view.minimumSize); + return size < snapSize ? 0 : item.view.minimumSize; + } + private distributeEmptySpace(): void { let contentSize = this.viewItems.reduce((r, i) => r + i.size, 0); let emptyDelta = this.size - contentSize; for (let i = this.viewItems.length - 1; emptyDelta !== 0 && i >= 0; i--) { const item = this.viewItems[i]; - const size = clamp(item.size + emptyDelta, item.view.minimumSize, item.view.maximumSize); + const size = SplitView.clamp(item, item.size + emptyDelta); const viewDelta = size - item.size; emptyDelta -= viewDelta;