public resizeArea()

in web/src/app/common/resizable-pane/resizing-calculator.ts [114:221]


  public resizeArea(
    id: string,
    sizeInPx: number,
    ignoreMinimumSize: boolean = false,
  ): void {
    const areas = this.areaStates.value.map((area) => ({
      spec: area.spec,
      currentSize: area.currentSize,
    }));
    const resizeTarget = areas.find((area) => area.spec.id === id);
    if (!resizeTarget) {
      return;
    }
    if (resizeTarget.currentSize === sizeInPx) {
      return;
    }
    let restSizeDiff = sizeInPx - resizeTarget.currentSize;
    if (restSizeDiff > 0) {
      resizeTarget.currentSize = sizeInPx;
      // expand specified area, shrink others
      for (let i = 0; i < 100; i++) {
        // calculate shrink info without the expanding target
        const shrinkInfo = this.calculateShrinkableAreaInfo(
          areas.filter((area) => area.spec.id !== id),
        );
        if (shrinkInfo.nextShrinkAreaId === '') {
          resizeTarget.currentSize -= restSizeDiff;
          break;
        }
        if (
          restSizeDiff <
          shrinkInfo.maxShrinkableSizeBeforeReachingMinSizeOfMinShrinkableArea
        ) {
          // Resize can be done without reaching the minSize
          let restSumOfShrinkRatio = shrinkInfo.sumOfShrinkableResizeRatio;
          for (const area of areas) {
            if (area.spec.resizeRatio === 0) continue;
            if (area.spec.id === id) 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 {
          const areaReachingTheLimit = areas.find(
            (area) => area.spec.id === shrinkInfo.nextShrinkAreaId,
          )!;
          const diff =
            areaReachingTheLimit.currentSize -
            areaReachingTheLimit.spec.minSizeInPx;
          restSizeDiff -= diff;
          areaReachingTheLimit.currentSize =
            areaReachingTheLimit.spec.minSizeInPx;
          let restSumOfShrinkRatio =
            shrinkInfo.sumOfShrinkableResizeRatio -
            areaReachingTheLimit.spec.resizeRatio;
          let restSizeDiffInThisLoop =
            shrinkInfo.maxShrinkableSizeBeforeReachingMinSizeOfMinShrinkableArea -
            diff;
          for (const area of areas) {
            if (area.spec.resizeRatio === 0) continue;
            if (area.spec.id === id) 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;
          }
        }
      }
    } else {
      // shrink specified area, expand others
      if (sizeInPx < resizeTarget.spec.minSizeInPx && !ignoreMinimumSize) {
        sizeInPx = resizeTarget.spec.minSizeInPx;
        restSizeDiff = resizeTarget.currentSize - sizeInPx;
      }
      restSizeDiff = -restSizeDiff;
      let restSumOfExpandRatio = areas.reduce(
        (a, b) => a + b.spec.resizeRatio,
        0,
      );
      restSumOfExpandRatio -= resizeTarget.spec.resizeRatio;
      for (const area of areas) {
        if (area.spec.resizeRatio === 0) continue;
        if (area.spec.id === id) continue;
        const expandSize = Math.floor(
          (restSizeDiff / restSumOfExpandRatio) * area.spec.resizeRatio,
        );
        area.currentSize += expandSize;
        restSizeDiff -= expandSize;
        restSumOfExpandRatio -= area.spec.resizeRatio;
      }
      resizeTarget.currentSize = sizeInPx;
      // If the rest of areas are not expandable
      if (restSizeDiff > 0) {
        resizeTarget.currentSize += restSizeDiff;
      }
    }
    this.areaStates.next(areas);
  }