public void collapseFoldRegion(FoldRegion region) { assertIsDispatchThreadForEditor(); if (!region.isExpanded()) return; if (!myIsBatchFoldingProcessing) { LOG.error("Fold regions must be collapsed or expanded inside batchFoldProcessing() only."); } List<Caret> carets = myEditor.getCaretModel().getAllCarets(); for (Caret caret : carets) { LogicalPosition caretPosition = caret.getLogicalPosition(); int caretOffset = myEditor.logicalPositionToOffset(caretPosition); if (FoldRegionsTree.contains(region, caretOffset)) { if (myDoNotCollapseCaret) return; } } for (Caret caret : carets) { LogicalPosition caretPosition = caret.getLogicalPosition(); int caretOffset = myEditor.logicalPositionToOffset(caretPosition); if (FoldRegionsTree.contains(region, caretOffset)) { if (caret.getUserData(SAVED_CARET_POSITION) == null) { caret.putUserData(SAVED_CARET_POSITION, caretPosition.withoutVisualPositionInfo()); } } } myFoldRegionsProcessed = true; ((FoldRegionImpl) region).setExpandedInternal(false); notifyListenersOnFoldRegionStateChange(region); }
public void collapseFoldRegion(FoldRegion region) { assertIsDispatchThread(); if (!region.isExpanded()) return; if (!myIsBatchFoldingProcessing) { LOG.error("Fold regions must be collapsed or expanded inside batchFoldProcessing() only."); } LogicalPosition caretPosition = myEditor.getCaretModel().getLogicalPosition(); int caretOffset = myEditor.logicalPositionToOffset(caretPosition); if (FoldRegionsTree.contains(region, caretOffset)) { if (myDoNotCollapseCaret) return; if (!myCaretPositionSaved) { mySavedCaretX = caretPosition.column; mySavedCaretY = caretPosition.line; myCaretPositionSaved = true; } } int selectionStart = myEditor.getSelectionModel().getSelectionStart(); int selectionEnd = myEditor.getSelectionModel().getSelectionEnd(); if (FoldRegionsTree.contains(region, selectionStart - 1) || FoldRegionsTree.contains(region, selectionEnd)) myEditor.getSelectionModel().removeSelection(); myFoldRegionsProcessed = true; ((FoldRegionImpl) region).setExpandedInternal(false); notifyListenersOnFoldRegionStateChange(region); }
private void runBatchFoldingOperation(final Runnable operation, final boolean dontCollapseCaret) { assertIsDispatchThread(); boolean oldDontCollapseCaret = myDoNotCollapseCaret; myDoNotCollapseCaret |= dontCollapseCaret; boolean oldBatchFlag = myIsBatchFoldingProcessing; if (!oldBatchFlag) { mySavedCaretShift = myEditor.visibleLineToY(myEditor.getCaretModel().getVisualPosition().line) - myEditor.getScrollingModel().getVerticalScrollOffset(); } myIsBatchFoldingProcessing = true; myFoldTree.myCachedLastIndex = -1; operation.run(); myFoldTree.myCachedLastIndex = -1; if (!oldBatchFlag) { if (myFoldRegionsProcessed) { notifyBatchFoldingProcessingDone(); myFoldRegionsProcessed = false; } myIsBatchFoldingProcessing = false; } myDoNotCollapseCaret = oldDontCollapseCaret; }
public void documentChanged(DocumentEvent event) { if (((DocumentEx) event.getDocument()).isInBulkUpdate()) { myFoldTree.clear(); } else { updateCachedOffsets(); } }
@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; }
public int getFoldedLinesCountBefore(int offset) { if (!myDocumentChangeProcessed && myEditor.getDocument().isInEventsHandling()) { // There is a possible case that this method is called on document update before fold regions // are recalculated. // We return zero in such situations then. return 0; } return myFoldTree.getFoldedLinesCountBefore(offset); }
@Override @Nullable public FoldRegion getFoldingPlaceholderAt(Point p) { assertReadAccess(); LogicalPosition pos = myEditor.xyToLogicalPosition(p); int line = pos.line; if (line >= myEditor.getDocument().getLineCount()) return null; int offset = myEditor.logicalPositionToOffset(pos); return myFoldTree.fetchOutermost(offset); }
public void removeFoldRegion(@NotNull final FoldRegion region) { assertIsDispatchThread(); if (!myIsBatchFoldingProcessing) { LOG.error("Fold regions must be added or removed inside batchFoldProcessing() only."); } region.setExpanded(true); final FoldingGroup group = region.getGroup(); if (group != null) { myGroups.removeValue(group, region); } myFoldTree.removeRegion(region); myFoldRegionsProcessed = true; region.dispose(); }
public void expandFoldRegion(FoldRegion region) { assertIsDispatchThread(); if (region.isExpanded() || region.shouldNeverExpand()) return; if (!myIsBatchFoldingProcessing) { LOG.error("Fold regions must be collapsed or expanded inside batchFoldProcessing() only."); } if (myCaretPositionSaved) { int savedOffset = myEditor.logicalPositionToOffset(new LogicalPosition(mySavedCaretY, mySavedCaretX)); FoldRegion[] allCollapsed = myFoldTree.fetchCollapsedAt(savedOffset); if (allCollapsed.length == 1 && allCollapsed[0] == region) { LogicalPosition pos = new LogicalPosition(mySavedCaretY, mySavedCaretX); myEditor.getCaretModel().moveToLogicalPosition(pos); } } myFoldRegionsProcessed = true; ((FoldRegionImpl) region).setExpandedInternal(true); notifyListenersOnFoldRegionStateChange(region); }
public void expandFoldRegion(FoldRegion region) { assertIsDispatchThreadForEditor(); if (region.isExpanded() || region.shouldNeverExpand()) return; if (!myIsBatchFoldingProcessing) { LOG.error("Fold regions must be collapsed or expanded inside batchFoldProcessing() only."); } for (Caret caret : myEditor.getCaretModel().getAllCarets()) { LogicalPosition savedPosition = caret.getUserData(SAVED_CARET_POSITION); if (savedPosition != null) { int savedOffset = myEditor.logicalPositionToOffset(savedPosition); FoldRegion[] allCollapsed = myFoldTree.fetchCollapsedAt(savedOffset); if (allCollapsed.length == 1 && allCollapsed[0] == region) { caret.moveToLogicalPosition(savedPosition); } } } myFoldRegionsProcessed = true; ((FoldRegionImpl) region).setExpandedInternal(true); notifyListenersOnFoldRegionStateChange(region); }
public FoldRegion[] fetchVisible() { return myFoldTree.fetchVisible(); }
public FoldRegion[] fetchCollapsedAt(int offset) { return myFoldTree.fetchCollapsedAt(offset); }
@Override public boolean intersectsRegion(int startOffset, int endOffset) { return myFoldTree.intersectsRegion(startOffset, endOffset); }
@Override @Nullable public FoldRegion[] fetchTopLevel() { return myFoldTree.fetchTopLevel(); }
@Override @Nullable public FoldRegion fetchOutermost(int offset) { return myFoldTree.fetchOutermost(offset); }
void onBulkDocumentUpdateFinished() { myFoldTree.rebuild(); }
@Override @Nullable public FoldRegion getCollapsedRegionAtOffset(int offset) { return myFoldTree.fetchOutermost(offset); }
private void notifyBatchFoldingProcessingDone(final boolean moveCaretFromCollapsedRegion) { rebuild(); for (FoldingListener listener : myListeners) { listener.onFoldProcessingEnd(); } myEditor.updateCaretCursor(); myEditor.recalculateSizeAndRepaint(); myEditor.getGutterComponentEx().updateSize(); myEditor.getGutterComponentEx().repaint(); 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); LogicalPosition savedPosition = caret.getUserData(SAVED_CARET_POSITION); if (savedPosition != null) { int savedOffset = myEditor.logicalPositionToOffset(savedPosition); FoldRegion collapsedAtSaved = myFoldTree.fetchOutermost(savedOffset); if (collapsedAtSaved == null) { positionToUse = savedPosition; } else { offsetToUse = collapsedAtSaved.getStartOffset(); } } if (collapsed != null && positionToUse == null) { positionToUse = myEditor.offsetToLogicalPosition(collapsed.getStartOffset()); } if (moveCaretFromCollapsedRegion && caret.isUpToDate()) { if (offsetToUse >= 0) { caret.moveToOffset(offsetToUse); } else if (positionToUse != null) { caret.moveToLogicalPosition(positionToUse); } else { caret.moveToLogicalPosition(caretPosition); } } caret.putUserData(SAVED_CARET_POSITION, savedPosition); 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 rebuild() { if (!myEditor.getDocument().isInBulkUpdate()) { myFoldTree.rebuild(); } }
public int getFoldedLinesCountBefore(int offset) { return myFoldTree.getFoldedLinesCountBefore(offset); }
@Override public void rebuild() { myFoldTree.rebuild(); }
public void doClearFoldRegions() { myGroups.clear(); myFoldTree.clear(); }
@Override public String toString() { return Arrays.toString(myFoldTree.fetchTopLevel()); }
@Nullable @Override public FoldRegion getFoldRegion(int startOffset, int endOffset) { assertReadAccess(); return myFoldTree.getRegionAt(startOffset, endOffset); }
@Override public int getLastCollapsedRegionBefore(int offset) { return myFoldTree.getLastTopLevelIndexBefore(offset); }
private void updateCachedOffsets() { myFoldTree.updateCachedOffsets(); }
void onBulkDocumentUpdateStarted() { myFoldTree.clearCachedValues(); }
private void doNotifyBatchFoldingProcessingDone() { 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 (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(); } }
@NotNull @Override public String dumpState() { return Arrays.toString(myFoldTree.fetchTopLevel()); }
@Override @NotNull public FoldRegion[] getAllFoldRegions() { assertReadAccess(); return myFoldTree.fetchAllRegions(); }