@Override
    public void run(boolean softWrapAware) {
      if (!softWrapAware) {
        return;
      }

      try {
        for (FoldRegionInfo info : myDeferredFoldRegions) {
          // There is a possible case that given fold region is contained inside another collapsed
          // fold region. We don't want to process
          // such nested region then.
          FoldRegion outerRegion =
              myEditor.getFoldingModel().getCollapsedRegionAtOffset(info.start);
          if (outerRegion != null
              && outerRegion != info.region
              && outerRegion.getStartOffset() <= info.start
              && outerRegion.getEndOffset() >= info.end) {
            continue;
          }

          for (SoftWrapFoldingListener listener : myFoldListeners) {
            listener.onFoldRegionStateChange(info.start, info.end);
          }
        }
      } finally {
        myDeferredFoldRegions.clear();
      }

      for (SoftWrapFoldingListener listener : myFoldListeners) {
        listener.onFoldProcessingEnd();
      }
    }
  @Override
  public void onFoldRegionStateChange(@NotNull FoldRegion region) {
    myUpdateInProgress = true;
    if (!isSoftWrappingEnabled() || !region.isValid()) {
      myDirty = true;
      return;
    }

    // We delay processing of changed fold regions till the invocation of onFoldProcessingEnd(), as
    // FoldingModel can return inconsistent data before that moment.
    myDeferredFoldRegions.add(new TextRange(region.getStartOffset(), region.getEndOffset()));
  }
  @Override
  public void onFoldRegionStateChange(@NotNull FoldRegion region) {
    myUpdateInProgress = true;
    if (!isSoftWrappingEnabled() || !region.isValid()) {
      myDirty = true;
      return;
    }

    myDeferredFoldRegions.add(new FoldRegionInfo(region));
  }
 FoldRegionInfo(@NotNull FoldRegion region) {
   this.region = region;
   start = region.getStartOffset();
   end = region.getEndOffset();
 }