@Override public boolean addFoldRegion(@NotNull final FoldRegion region) { assertIsDispatchThreadForEditor(); if (!isFoldingEnabled()) { return false; } if (!myIsBatchFoldingProcessing) { LOG.error("Fold regions must be added or removed inside batchFoldProcessing() only."); return false; } myFoldRegionsProcessed = true; if (myFoldTree.addRegion(region)) { final FoldingGroup group = region.getGroup(); if (group != null) { myGroups.putValue(group, region); } for (FoldingListener listener : myListeners) { listener.onFoldRegionStateChange(region); } return true; } return false; }
@Override public void addListener(@NotNull FoldingListener listener, @NotNull Disposable parentDisposable) { myDelegate.addListener(listener, parentDisposable); }
private void notifyBatchFoldingProcessingDone(final boolean moveCaretFromCollapsedRegion) { myFoldTree.rebuild(); for (FoldingListener listener : myListeners) { listener.onFoldProcessingEnd(); } myEditor.updateCaretCursor(); myEditor.recalculateSizeAndRepaint(); if (myEditor.getGutterComponentEx().isFoldingOutlineShown()) { myEditor.getGutterComponentEx().repaint(); } LogicalPosition caretPosition = myEditor.getCaretModel().getLogicalPosition(); // There is a possible case that caret position is already visual position aware. But visual position depends on number of folded // logical lines as well, hence, we can't be sure that target logical position defines correct visual position because fold // regions have just changed. Hence, we use 'raw' logical position instead. if (caretPosition.visualPositionAware) { caretPosition = new LogicalPosition(caretPosition.line, caretPosition.column); } int caretOffset = myEditor.logicalPositionToOffset(caretPosition); boolean hasBlockSelection = myEditor.getSelectionModel().hasBlockSelection(); int selectionStart = myEditor.getSelectionModel().getSelectionStart(); int selectionEnd = myEditor.getSelectionModel().getSelectionEnd(); int column = -1; int line = -1; int offsetToUse = -1; FoldRegion collapsed = myFoldTree.fetchOutermost(caretOffset); if (myCaretPositionSaved) { int savedOffset = myEditor.logicalPositionToOffset(new LogicalPosition(mySavedCaretY, mySavedCaretX)); FoldRegion collapsedAtSaved = myFoldTree.fetchOutermost(savedOffset); if (collapsedAtSaved == null) { column = mySavedCaretX; line = mySavedCaretY; } else { offsetToUse = collapsedAtSaved.getStartOffset(); } } if (collapsed != null && column == -1) { line = collapsed.getDocument().getLineNumber(collapsed.getStartOffset()); column = myEditor.offsetToLogicalPosition(collapsed.getStartOffset()).column; } boolean oldCaretPositionSaved = myCaretPositionSaved; if (moveCaretFromCollapsedRegion && myEditor.getCaretModel().isUpToDate()) { if (offsetToUse >= 0) { myEditor.getCaretModel().moveToOffset(offsetToUse); } else if (column != -1) { myEditor.getCaretModel().moveToLogicalPosition(new LogicalPosition(line, column)); } else { myEditor.getCaretModel().moveToLogicalPosition(caretPosition); } } myCaretPositionSaved = oldCaretPositionSaved; if (!hasBlockSelection && selectionStart < myEditor.getDocument().getTextLength()) { myEditor.getSelectionModel().setSelection(selectionStart, selectionEnd); } if (mySavedCaretShift > 0) { myEditor.getScrollingModel().disableAnimation(); int scrollTo = myEditor.visibleLineToY(myEditor.getCaretModel().getVisualPosition().line) - mySavedCaretShift; myEditor.getScrollingModel().scrollVertically(scrollTo); myEditor.getScrollingModel().enableAnimation(); } }
@Override public boolean addListener(@NotNull FoldingListener listener) { return myListeners.add(listener); }
@Override public boolean removeListener(@NotNull FoldingListener listener) { return myListeners.remove(listener); }
private void notifyListenersOnFoldRegionStateChange(@NotNull FoldRegion foldRegion) { for (FoldingListener listener : myListeners) { listener.onFoldRegionStateChange(foldRegion); } }
@Override public boolean addListener(@NotNull FoldingListener listener) { return myDelegate.addListener(listener); }
@Override public boolean removeListener(@NotNull FoldingListener listener) { return myDelegate.removeListener(listener); }
private void notifyBatchFoldingProcessingDone(final boolean moveCaretFromCollapsedRegion) { clearCachedValues(); for (FoldingListener listener : myListeners) { listener.onFoldProcessingEnd(); } myEditor.updateCaretCursor(); myEditor.recalculateSizeAndRepaint(); myEditor.getGutterComponentEx().updateSize(); myEditor.getGutterComponentEx().repaint(); myEditor.invokeDelayedErrorStripeRepaint(); for (Caret caret : myEditor.getCaretModel().getAllCarets()) { // There is a possible case that caret position is already visual position aware. But visual position depends on number of folded // logical lines as well, hence, we can't be sure that target logical position defines correct visual position because fold // regions have just changed. Hence, we use 'raw' logical position instead. LogicalPosition caretPosition = caret.getLogicalPosition().withoutVisualPositionInfo(); int caretOffset = myEditor.logicalPositionToOffset(caretPosition); int selectionStart = caret.getSelectionStart(); int selectionEnd = caret.getSelectionEnd(); LogicalPosition positionToUse = null; int offsetToUse = -1; FoldRegion collapsed = myFoldTree.fetchOutermost(caretOffset); SavedCaretPosition savedPosition = caret.getUserData(SAVED_CARET_POSITION); boolean markedForUpdate = caret.getUserData(MARK_FOR_UPDATE) != null; if (savedPosition != null && savedPosition.isUpToDate(myEditor)) { int savedOffset = myEditor.logicalPositionToOffset(savedPosition.position); FoldRegion collapsedAtSaved = myFoldTree.fetchOutermost(savedOffset); if (collapsedAtSaved == null) { positionToUse = savedPosition.position; } else { offsetToUse = collapsedAtSaved.getStartOffset(); } } if (collapsed != null && positionToUse == null) { positionToUse = myEditor.offsetToLogicalPosition(collapsed.getStartOffset()); } if ((markedForUpdate || moveCaretFromCollapsedRegion) && caret.isUpToDate()) { if (offsetToUse >= 0) { caret.moveToOffset(offsetToUse); } else if (positionToUse != null) { caret.moveToLogicalPosition(positionToUse); } else { ((CaretImpl)caret).updateVisualPosition(); } } caret.putUserData(SAVED_CARET_POSITION, savedPosition); caret.putUserData(MARK_FOR_UPDATE, null); if (isOffsetInsideCollapsedRegion(selectionStart) || isOffsetInsideCollapsedRegion(selectionEnd)) { caret.removeSelection(); } else if (selectionStart < myEditor.getDocument().getTextLength()) { caret.setSelection(selectionStart, selectionEnd); } } if (mySavedCaretShift > 0) { final ScrollingModel scrollingModel = myEditor.getScrollingModel(); scrollingModel.disableAnimation(); scrollingModel.scrollVertically(myEditor.visibleLineToY(myEditor.getCaretModel().getVisualPosition().line) - mySavedCaretShift); scrollingModel.enableAnimation(); } }
@Override public void addListener(@Nonnull final FoldingListener listener, @Nonnull Disposable parentDisposable) { myListeners.add(listener); Disposer.register(parentDisposable, () -> myListeners.remove(listener)); }
private void notifyListenersOnFoldRegionStateChange(@Nonnull FoldRegion foldRegion) { for (FoldingListener listener : myListeners) { listener.onFoldRegionStateChange(foldRegion); } }
@Override public void addListener(@Nonnull FoldingListener listener, @Nonnull Disposable parentDisposable) { myDelegate.addListener(listener, parentDisposable); }