in web/src/app/common/resizable-pane/resizing-calculator.ts [227:323]
private constraintByContainerSize(
areaSizeState: ResizableAreaState[],
containerSize: number,
): ResizableAreaState[] {
areaSizeState = areaSizeState.map((area) => ({
spec: area.spec,
currentSize: area.currentSize,
}));
const currentSize = this.getEntirePaneSize(areaSizeState);
if (currentSize === containerSize) return areaSizeState;
const minSize = this.getMinimumEntireAreaSize(areaSizeState);
// contents can't be fit in the container even with the minimum size. override container size as the last way.
if (containerSize < minSize) {
containerSize = minSize;
for (const area of areaSizeState) {
area.currentSize = area.spec.minSizeInPx;
}
return areaSizeState;
}
if (currentSize < containerSize) {
// Expanding areas
let restSizeDiff = containerSize - currentSize;
let restSumOfExpandRatio = areaSizeState.reduce(
(a, b) => a + b.spec.resizeRatio,
0,
);
for (const area of areaSizeState) {
if (area.spec.resizeRatio === 0) continue;
const expandSize = Math.floor(
(restSizeDiff / restSumOfExpandRatio) * area.spec.resizeRatio,
);
area.currentSize += expandSize;
restSizeDiff -= expandSize;
restSumOfExpandRatio -= area.spec.resizeRatio;
}
return areaSizeState;
} else {
// Shrinking area
// Shrink operation is not straight because each areas can have different minSizeInPx even they had non-zero resizeRatio
let restSizeDiff = currentSize - containerSize;
for (let i = 0; i < 100; i++) {
// Loops until the specific times to avoid infinity loop if bug occurs
const shrinkInfo = this.calculateShrinkableAreaInfo(areaSizeState);
// No shrinkable area anymore, but here should be unreachable.
if (shrinkInfo.nextShrinkAreaId === '') return areaSizeState;
if (
restSizeDiff <
shrinkInfo.maxShrinkableSizeBeforeReachingMinSizeOfMinShrinkableArea
) {
// Resize can be done without reaching the minSize
let restSumOfShrinkRatio = shrinkInfo.sumOfShrinkableResizeRatio;
for (const area of areaSizeState) {
if (area.spec.resizeRatio === 0) continue;
if (area.spec.minSizeInPx === area.currentSize) continue;
const shrinkSize = Math.floor(
(restSizeDiff / restSumOfShrinkRatio) * area.spec.resizeRatio,
);
area.currentSize -= shrinkSize;
restSizeDiff -= shrinkSize;
restSumOfShrinkRatio -= area.spec.resizeRatio;
}
break;
} else {
// Resize can't be done without reaching the minSize of the area
const nextShrinkAreaReachingLimit = areaSizeState.find(
(area) => area.spec.id === shrinkInfo.nextShrinkAreaId,
)!;
const diff =
nextShrinkAreaReachingLimit.currentSize -
nextShrinkAreaReachingLimit.spec.minSizeInPx;
restSizeDiff -= diff;
nextShrinkAreaReachingLimit.currentSize =
nextShrinkAreaReachingLimit.spec.minSizeInPx;
let restSumOfShrinkRatio =
shrinkInfo.sumOfShrinkableResizeRatio -
nextShrinkAreaReachingLimit.spec.resizeRatio;
let restSizeDiffInThisLoop =
shrinkInfo.maxShrinkableSizeBeforeReachingMinSizeOfMinShrinkableArea -
diff;
for (const area of areaSizeState) {
if (area.spec.resizeRatio === 0) continue;
if (area.spec.minSizeInPx === area.currentSize) continue;
const shrinkSize = Math.floor(
(restSizeDiffInThisLoop / restSumOfShrinkRatio) *
area.spec.resizeRatio,
);
area.currentSize -= shrinkSize;
restSizeDiff -= shrinkSize;
restSizeDiffInThisLoop -= shrinkSize;
restSumOfShrinkRatio -= area.spec.resizeRatio;
}
}
}
return areaSizeState;
}
}