Merge remote-tracking branch 'origin/master'

This commit is contained in:
Alexander Lobas
2012-04-13 13:24:53 +04:00
12 changed files with 323 additions and 94 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -94,7 +94,7 @@ public class BaseIndentEnterHandler extends EnterHandlerDelegateAdapter {
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
int caret = editor.getCaretModel().getOffset();
if (caret == 0) {
if (caret <= 0) {
return Result.Continue;
}
@@ -774,6 +774,16 @@ public class EditorWindow extends UserDataHolderBase implements EditorEx {
myDelegate.setStickySelection(enable);
}
@Override
public boolean isPurePaintingMode() {
return myDelegate.isPurePaintingMode();
}
@Override
public void setPurePaintingMode(boolean enabled) {
myDelegate.setPurePaintingMode(enabled);
}
@Override
public void setPrefixTextAndAttributes(@Nullable String prefixText, @Nullable TextAttributes attributes) {
myDelegate.setPrefixTextAndAttributes(prefixText, attributes);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,17 +36,17 @@ public interface LineWrapPositionStrategy {
*
* @param document target document which text is being processed
* @param project target project
* @param startOffset start offset to use with the given text holder (inclusive)
* @param startOffset start offset to use with the given text holder (exclusive)
* @param endOffset end offset to use with the given text holder (exclusive)
* @param maxPreferredOffset this method is expected to do its best to return offset that belongs to
* <code>(startOffset; maxPreferredOffset]</code> interval. However, it's allowed
* to return value from <code>(maxPreferredOffset; endOffset]</code> interval
* to return value from <code>(maxPreferredOffset; endOffset)</code> interval
* unless <code>'allowToBeyondMaxPreferredOffset'</code> if <code>'false'</code>
* @param allowToBeyondMaxPreferredOffset indicates if it's allowed to return value from
* <code>(maxPreferredOffset; endOffset]</code> interval in case of inability to
* find appropriate offset from <code>(startOffset; maxPreferredOffset]</code> interval
* @param virtual identifies if current request is for virtual wrap (soft wrap) position
* @return offset from <code>(startOffset; endOffset]</code> interval where
* @return offset from <code>(startOffset; endOffset)</code> interval where
* target line should be wrapped OR <code>-1</code> if no wrapping should be performed
*/
int calculateWrapPosition(
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -89,7 +89,13 @@ public class EditorFragmentComponent extends JPanel {
textGraphics.translate(0, -y1);
textGraphics.setClip(0, y1, textWidth, height);
final boolean wasVisible = editor.setCaretVisible(false);
editor.getContentComponent().paint(textGraphics);
editor.setPurePaintingMode(true);
try {
editor.getContentComponent().paint(textGraphics);
}
finally {
editor.setPurePaintingMode(false);
}
if (wasVisible) {
editor.setCaretVisible(true);
}
@@ -203,6 +203,12 @@ public interface EditorEx extends Editor {
*/
void setStickySelection(boolean enable);
/**
* @return width in pixels of the {@link #setPrefixTextAndAttributes(String, TextAttributes) prefix} used with the current editor if any;
* zero otherwise
*/
int getPrefixTextWidthInPixels();
/**
* Allows to define prefix to be displayed on every editor line and text attributes to use for its coloring.
*
@@ -212,8 +218,21 @@ public interface EditorEx extends Editor {
void setPrefixTextAndAttributes(@Nullable String prefixText, @Nullable TextAttributes attributes);
/**
* @return width in pixels of the {@link #setPrefixTextAndAttributes(String, TextAttributes) prefix} used with the current editor if any;
* zero otherwise
* @return current 'pure painting mode' status
* @see #setPurePaintingMode(boolean)
*/
int getPrefixTextWidthInPixels();
boolean isPurePaintingMode();
/**
* We often re-use the logic encapsulated at the editor. For example, every time we show editor fragment (folding, preview etc) we
* create a dedicated graphics object and ask the editor to paint into it.
* <p/>
* The thing is that the editor itself may change its state if any postponed operation is triggered by the painting request
* (e.g. soft wraps recalculation is triggered by the paint request and newly calculated soft wraps cause caret to change its position).
* <p/>
* This method allows to inform the editor that all subsequent painting request should not change the editor state.
*
* @param enabled 'pure painting mode' status to use
*/
void setPurePaintingMode(boolean enabled);
}
@@ -116,7 +116,9 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
@Override
public void updateFinished(@NotNull Document doc) {
if (doc != myEditor.getDocument() || myIsInUpdate) return;
if (savedBeforeBulkCaretMarker != null && savedBeforeBulkCaretMarker.isValid()) {
if (savedBeforeBulkCaretMarker != null && savedBeforeBulkCaretMarker.isValid()
&& savedBeforeBulkCaretMarker.getStartOffset() != myOffset)
{
moveToOffset(savedBeforeBulkCaretMarker.getStartOffset());
}
releaseBulkCaretMarker();
@@ -285,6 +285,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private int myStickySelectionStart;
private boolean myScrollToCaret = true;
private boolean myPurePaintingMode;
private boolean myPaintSelection;
private final EditorSizeAdjustmentStrategy mySizeAdjustmentStrategy = new EditorSizeAdjustmentStrategy();
@@ -499,6 +500,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
}
@Override
public int getPrefixTextWidthInPixels() {
return myPrefixWidthInPixels;
}
@Override
public void setPrefixTextAndAttributes(@Nullable String prefixText, @Nullable TextAttributes attributes) {
myPrefixText = prefixText == null ? null: prefixText.toCharArray();
@@ -513,8 +519,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
@Override
public int getPrefixTextWidthInPixels() {
return myPrefixWidthInPixels;
public boolean isPurePaintingMode() {
return myPurePaintingMode;
}
@Override
public void setPurePaintingMode(boolean enabled) {
myPurePaintingMode = enabled;
}
@Override
@@ -2001,7 +2012,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
boolean locateBeforeSoftWrap = !SoftWrapHelper.isCaretAfterSoftWrap(this);
int start = clipStartOffset;
int end = clipEndOffset;
getSoftWrapModel().registerSoftWrapsIfNecessary();
if (!myPurePaintingMode) {
getSoftWrapModel().registerSoftWrapsIfNecessary();
}
LineIterator lIterator = createLineIterator();
lIterator.start(start);
@@ -222,7 +222,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
@Override
public boolean isSoftWrappingEnabled() {
if (!myUseSoftWraps || myEditor.isOneLineMode()) {
if (!myUseSoftWraps || myEditor.isOneLineMode() || myEditor.isPurePaintingMode()) {
return false;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,10 +25,7 @@ import gnu.trove.TObjectProcedure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.*;
/**
* Encapsulates information to cache for the single visual line.
@@ -131,6 +128,23 @@ class CacheEntry implements Comparable<CacheEntry>, Cloneable {
return result;
}
/**
* Removes fold data for all fold regions that start at or after the given offset.
*
* @param offset target offset
*/
public void removeAllFoldDataAtOrAfter(final int offset) {
if (myFoldingData == DUMMY || myFoldingData.isEmpty()) {
return;
}
myFoldingData.retainEntries(new TIntObjectProcedure<FoldingData>() {
@Override
public boolean execute(int a, FoldingData b) {
return a < offset;
}
});
}
@Nullable
public FoldingData getFoldingData(@NotNull final FoldRegion region) {
FoldingData candidate = myFoldingData.get(region.getStartOffset());
@@ -285,7 +285,11 @@ public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAw
@Override
public void revertToOffset(final int offset, int visualLine) {
// Do nothing in assumption that we store only information about start and end visual line positions and
final CacheEntry entry = getCacheEntryForVisualLine(visualLine, false);
if (entry != null) {
entry.removeAllFoldDataAtOrAfter(offset);
}
// Do nothing more in assumption that we store only information about start and end visual line positions and
// that start information remains the same and end of line is not reached yet.
}
@@ -24,6 +24,7 @@ import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.editor.event.VisibleAreaEvent;
import com.intellij.openapi.editor.event.VisibleAreaListener;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.ScrollingModelEx;
import com.intellij.openapi.editor.ex.util.EditorUtil;
@@ -80,7 +81,6 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
private final SoftWrapsStorage myStorage;
private final EditorEx myEditor;
private final SoftWrapPainter myPainter;
private final EditorTextRepresentationHelper myRepresentationHelper;
private final SoftWrapDataMapper myDataMapper;
/**
@@ -93,15 +93,16 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
*/
private int myLastTopLeftCornerOffset = -1;
private VisibleAreaWidthProvider myWidthProvider;
private LineWrapPositionStrategy myLineWrapPositionStrategy;
private IncrementalCacheUpdateEvent myEventBeingProcessed;
private boolean myVisualAreaListenerAttached;
private boolean myCustomIndentUsedLastTime;
private int myCustomIndentValueUsedLastTime;
private int myVisibleAreaWidth;
private boolean myInProgress;
private boolean myHasLinesWithFailedWrap;
private VisibleAreaWidthProvider myWidthProvider;
private EditorTextRepresentationHelper myRepresentationHelper;
private LineWrapPositionStrategy myLineWrapPositionStrategy;
private IncrementalCacheUpdateEvent myEventBeingProcessed;
private boolean myVisualAreaListenerAttached;
private boolean myCustomIndentUsedLastTime;
private int myCustomIndentValueUsedLastTime;
private int myVisibleAreaWidth;
private boolean myInProgress;
private boolean myHasLinesWithFailedWrap;
public SoftWrapApplianceManager(@NotNull SoftWrapsStorage storage,
@NotNull EditorEx editor,
@@ -303,6 +304,7 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
* @param foldRegion target collapsed fold region to process
* @return <code>true</code> if processing should be continued; <code>false</code> otherwise
*/
@SuppressWarnings("MagicConstant")
private boolean processCollapsedFoldRegion(FoldRegion foldRegion) {
if (processOutOfDateFoldRegion(foldRegion)) {
return false;
@@ -312,10 +314,9 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
if (placeholder.isEmpty()) {
return true;
}
FontInfo fontInfo = EditorUtil.fontForChar(placeholder.charAt(0), myContext.fontType, myEditor);
int placeholderWidthInPixels = 0;
for (int i = 0; i < placeholder.length(); i++) {
placeholderWidthInPixels += fontInfo.charWidth(placeholder.charAt(i));
placeholderWidthInPixels += myRepresentationHelper.charWidth(placeholder.charAt(i), myContext.fontType);
}
int newX = myContext.currentPosition.x + placeholderWidthInPixels;
@@ -491,19 +492,50 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
}
}
@SuppressWarnings("MagicConstant")
private void createSoftWrapIfPossible() {
final int offset = myContext.currentPosition.offset;
myContext.logicalLineData.update(offset);
int softWrapStartOffset = myContext.softWrapStartOffset;
int preferredOffset = Math.max(softWrapStartOffset, offset - 1 /* reserve a column for the soft wrap sign */);
SoftWrap softWrap = registerSoftWrap(
softWrapStartOffset, Math.max(softWrapStartOffset, offset),
calculateSoftWrapEndOffset(softWrapStartOffset, myContext.logicalLineData.endLineOffset), myContext.getSpaceWidth(),
softWrapStartOffset,
preferredOffset,
calculateSoftWrapEndOffset(softWrapStartOffset, myContext.logicalLineData.endLineOffset),
myContext.getSpaceWidth(),
myContext.logicalLineData
);
boolean revertedToFoldRegion = false;
if (softWrap == null) {
myContext.tryToShiftToNextLine();
myHasLinesWithFailedWrap = true;
return;
EditorPosition wrapPosition = null;
// Try to insert soft wrap after the last collapsed fold region that is located on the current visual line.
if (myContext.lastFoldEndPosition != null && myStorage.getSoftWrap(myContext.lastFoldEndPosition.offset) == null
&& myContext.lastFoldEndPosition.offset + 1/* reserve one visual column for the soft wrap sign */
< myContext.currentPosition.offset)
{
wrapPosition = myContext.lastFoldEndPosition;
}
if (wrapPosition == null && myContext.lastFoldStartPosition != null
&& myStorage.getSoftWrap(myContext.lastFoldStartPosition.offset) == null
&& myContext.lastFoldStartPosition.offset < myContext.currentPosition.offset)
{
wrapPosition = myContext.lastFoldStartPosition;
}
if (wrapPosition != null){
revertListeners(wrapPosition.offset, wrapPosition.visualLine);
myContext.currentPosition = wrapPosition;
softWrap = registerSoftWrap(wrapPosition.offset, myContext.getSpaceWidth(), myContext.logicalLineData);
myContext.tokenStartOffset = wrapPosition.offset;
revertedToFoldRegion = true;
}
else {
myContext.tryToShiftToNextLine();
myHasLinesWithFailedWrap = true;
return;
}
}
myContext.skipToLineEnd = false;
@@ -528,14 +560,16 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
return;
}
else if (actualSoftWrapOffset < offset) {
revertListeners(actualSoftWrapOffset, myContext.currentPosition.visualLine);
for (int j = offset - 1; j >= actualSoftWrapOffset; j--) {
int pixelsDiff = myOffset2widthInPixels.data[j - myOffset2widthInPixels.anchor];
int tmpFontType = myOffset2fontType.get(j);
int columnsDiff = calculateWidthInColumns(myContext.text.charAt(j), pixelsDiff, myContext.getSpaceWidth(tmpFontType));
myContext.currentPosition.offset--;
myContext.currentPosition.logicalColumn -= columnsDiff;
myContext.currentPosition.visualColumn -= columnsDiff;
if (!revertedToFoldRegion) {
revertListeners(actualSoftWrapOffset, myContext.currentPosition.visualLine);
for (int j = offset - 1; j >= actualSoftWrapOffset; j--) {
int pixelsDiff = myOffset2widthInPixels.data[j - myOffset2widthInPixels.anchor];
int tmpFontType = myOffset2fontType.get(j);
int columnsDiff = calculateWidthInColumns(myContext.text.charAt(j), pixelsDiff, myContext.getSpaceWidth(tmpFontType));
myContext.currentPosition.offset--;
myContext.currentPosition.logicalColumn -= columnsDiff;
myContext.currentPosition.visualColumn -= columnsDiff;
}
}
}
else if (actualSoftWrapOffset > offset) {
@@ -549,6 +583,10 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
myContext.currentPosition.offset = actualSoftWrapOffset;
myOffset2fontType.clear();
myOffset2widthInPixels.clear();
if (revertedToFoldRegion && myContext.currentPosition.offset == myContext.lastFold.getStartOffset()) {
processCollapsedFoldRegion(myContext.lastFold);
}
}
private int calculateNewX(char c) {
@@ -570,7 +608,7 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
return i;
}
}
return end;
return Math.max(start, end);
}
private static int calculateWidthInColumns(char c, int widthInPixels, int spaceWithInPixels) {
@@ -619,7 +657,9 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
}
if (softWrapOffset >= lineData.endLineOffset || softWrapOffset < 0
|| (myCustomIndentUsedLastTime && softWrapOffset == lineData.nonWhiteSpaceSymbolOffset))
|| (myCustomIndentUsedLastTime && softWrapOffset == lineData.nonWhiteSpaceSymbolOffset)
|| (softWrapOffset > preferredOffset && myContext.lastFoldStartPosition != null // Prefer to wrap on fold region backwards
&& myContext.lastFoldStartPosition.offset <= preferredOffset)) // to wrapping forwards.
{
return null;
}
@@ -923,8 +963,14 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
recalculateIfNecessary();
}
public void setWidthProvider(VisibleAreaWidthProvider widthProvider) {
public void setWidthProvider(@NotNull VisibleAreaWidthProvider widthProvider) {
myWidthProvider = widthProvider;
reset();
}
public void setRepresentationHelper(@NotNull EditorTextRepresentationHelper representationHelper) {
myRepresentationHelper = representationHelper;
reset();
}
@NotNull
@@ -1132,6 +1178,14 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
public CharSequence text;
public EditorPosition lineStartPosition;
public EditorPosition currentPosition;
/**
* Start position of the last collapsed fold region that is located at the current visual line and can be used as a fall back
* position for soft wrapping.
*/
public EditorPosition lastFoldStartPosition;
public EditorPosition lastFoldEndPosition;
/** A fold region referenced by the {@link #lastFoldStartPosition}. */
public FoldRegion lastFold;
public SoftWrap delayedSoftWrap;
public JComponent contentComponent;
public int reservedWidthInPixels;
@@ -1156,6 +1210,9 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
text = null;
lineStartPosition = null;
currentPosition = null;
lastFoldStartPosition = null;
lastFoldEndPosition = null;
lastFold = null;
delayedSoftWrap = null;
contentComponent = null;
reservedWidthInPixels = 0;
@@ -1187,10 +1244,14 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
/**
* Asks current context to update its state assuming that it begins to point to the line next to its current position.
*/
@SuppressWarnings("MagicConstant")
public void onNewLine() {
notifyListenersOnVisualLineEnd();
currentPosition.onNewLine();
softWrapStartOffset = currentPosition.offset;
lastFoldStartPosition = null;
lastFoldEndPosition = null;
lastFold = null;
lineStartPosition.from(currentPosition);
logicalLineData.update(currentPosition.logicalLine, getSpaceWidth(), myEditor);
fontType = myOffset2fontType.get(currentPosition.offset);
@@ -1213,6 +1274,7 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
onNonLineFeedSymbol(c, newX);
}
@SuppressWarnings("MagicConstant")
public void onNonLineFeedSymbol(char c, int newX) {
int widthInPixels = newX - myContext.currentPosition.x;
@@ -1247,18 +1309,27 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
* @param foldRegion collapsed fold region to process
*/
private void advance(FoldRegion foldRegion, int placeHolderWidthInPixels) {
lastFoldStartPosition = currentPosition.clone();
lastFold = foldRegion;
int visualLineBefore = currentPosition.visualLine;
int logicalLineBefore = currentPosition.logicalLine;
int logicalColumnBefore = currentPosition.logicalColumn;
currentPosition.advance(foldRegion);
currentPosition.x += placeHolderWidthInPixels;
int collapsedFoldingWidthInColumns = currentPosition.logicalColumn;
if (currentPosition.visualLine <= visualLineBefore) {
if (currentPosition.logicalLine <= logicalLineBefore) {
// Single-line fold region.
collapsedFoldingWidthInColumns = currentPosition.logicalColumn - logicalColumnBefore;
}
else {
final DocumentEx document = myEditor.getDocument();
int endFoldLine = document.getLineNumber(foldRegion.getEndOffset());
logicalLineData.endLineOffset = document.getLineEndOffset(endFoldLine);
}
notifyListenersOnFoldRegion(foldRegion, collapsedFoldingWidthInColumns, visualLineBefore);
tokenStartOffset = myContext.currentPosition.offset;
softWrapStartOffset = foldRegion.getEndOffset();
lastFoldEndPosition = currentPosition.clone();
}
/**
@@ -1288,7 +1359,7 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
* @return <code>true</code> if given <code>'x'</code> coordinate exceeds visual area's right edge; <code>false</code> otherwise
*/
public boolean exceedsVisualEdge(int x) {
return x + reservedWidthInPixels >= myVisibleAreaWidth;
return x >= myVisibleAreaWidth;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,9 +17,7 @@ package com.intellij.openapi.editor.impl.softwrap.mapping;
import com.intellij.codeInsight.folding.CodeFoldingManager;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModificationTest;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.editor.impl.SoftWrapModelImpl;
import com.intellij.openapi.editor.impl.*;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.testFramework.TestFileType;
@@ -64,7 +62,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
public void testSoftWrapAdditionOnTyping() throws Exception {
String text =
"this is a test string that is expected to end just before right margin<caret>";
init(800, text);
init(100, text);
int offset = myEditor.getDocument().getTextLength() + 1;
assertTrue(getSoftWrapModel().getRegisteredSoftWraps().isEmpty());
@@ -86,7 +84,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"123\n" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
init(100, text);
init(15, text);
assertTrue(getSoftWrapModel().getRegisteredSoftWraps().isEmpty());
type('1');
assertTrue(getSoftWrapModel().getRegisteredSoftWraps().isEmpty());
@@ -105,7 +103,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
" }\n" +
"}";
init(300, text);
init(40, text);
final FoldingModel foldingModel = myEditor.getFoldingModel();
assertEmpty(foldingModel.getAllFoldRegions());
@@ -133,7 +131,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
" }\n" +
"}<caret>";
init(300, text);
init(40, text);
type('\n');
VisualPosition position = myEditor.getCaretModel().getVisualPosition();
assertEquals(new VisualPosition(5, 0), position);
@@ -148,7 +146,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"}\n" +
"abcde";
init(300, text);
init(40, text);
int offset = text.indexOf("abcde");
myEditor.getSelectionModel().setSelection(offset, text.length());
delete();
@@ -161,7 +159,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"}\n" +
"<caret>";
init(300, text);
init(40, text);
type('\t');
assertEquals(new VisualPosition(2, 4), myEditor.getCaretModel().getVisualPosition());
}
@@ -171,7 +169,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"line1\n" +
"long line<caret>";
init(48, text);
init(48, text, 7);
int softWrapsBefore = getSoftWrapModel().getRegisteredSoftWraps().size();
assertTrue(softWrapsBefore > 0);
@@ -191,7 +189,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
" }\n" +
"}";
init(700, text);
init(100, text);
int startFoldOffset = text.indexOf('@');
int endFoldOffset = text.indexOf(')');
@@ -215,7 +213,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"line5\n" +
"line6<caret>";
init(700, text);
init(100, text);
type("\nq");
assertEquals(new VisualPosition(7, 1), myEditor.offsetToVisualPosition(myEditor.getDocument().getTextLength()));
}
@@ -225,7 +223,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
String text =
"line1<caret>\n" +
"second line that is long enough to be soft wrapped";
init(100, text);
init(15, text);
TIntHashSet offsetsBefore = collectSoftWrapStartOffsets(1);
assertTrue(!offsetsBefore.isEmpty());
@@ -257,7 +255,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"ordinary line 7\n" +
"ordinary line 8\n";
init(200, text);
init(30, text);
LogicalPosition position = myEditor.visualToLogicalPosition(new VisualPosition(8, 0));
assertSame(7, position.line); // Position from soft-wrapped part of the line
@@ -274,7 +272,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
" */\n" +
"public class Test {\n" +
"}";
init(500, text);
init(100, text);
addCollapsedFoldRegion(0, text.indexOf("public") - 1, "/**...*/");
@@ -293,7 +291,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
// There was a problem that removing text from the last document line that was soft-wrapped removed soft wraps as well.
String text =
"This a long string that is expected to be wrapped in more than one visual line<caret>";
init(150, text);
init(20, text);
List<? extends SoftWrap> softWrapsBeforeModification = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
assertTrue(softWrapsBeforeModification.size() > 0);
@@ -307,7 +305,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
String text =
"Line1\n" +
"Long line2 that is expected to be soft-wrapped<caret>";
init(150, text);
init(20, text);
List<? extends SoftWrap> softWrapsBeforeModification = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
assertTrue(softWrapsBeforeModification.size() > 0);
@@ -331,7 +329,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"fold line3\n" +
"fold line4\n" +
"normal line1";
init(150, text);
init(20, text);
int afterFoldOffset = text.indexOf("normal line1");
addCollapsedFoldRegion(text.indexOf("fold line1") + 2, afterFoldOffset - 1, "...");
@@ -352,7 +350,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"line5\n" +
"this is long line that is expected to be soft-wrapped\n" +
"line6";
init(100, text);
init(15, text);
assertTrue(!getSoftWrapModel().getRegisteredSoftWraps().isEmpty());
@@ -392,7 +390,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
" */\n" +
"class Test {\n" +
"}";
init(700, text);
init(100, text);
String placeholder = "/**...*/";
addCollapsedFoldRegion(0, text.indexOf("class") - 1, placeholder);
@@ -417,7 +415,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
" */\n" +
"class Test {\n" +
"}";
init(700, text);
init(100, text);
String placeholder = "/**...*/";
addCollapsedFoldRegion(2, text.indexOf("class") - 1, placeholder);
@@ -436,7 +434,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"class Test {\n" +
"}";
init(700, text);
init(100, text);
int startOffset = text.indexOf("@");
int endOffset = text.indexOf("class") - 1;
addCollapsedFoldRegion(startOffset, endOffset, "xxx");
@@ -456,7 +454,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"line4\n" +
"line5";
init(30, text);
init(30, text, 7);
int start = text.indexOf("line3") - 1;
addCollapsedFoldRegion(start, text.length(), "...");
assertEquals(1, getSoftWrapModel().getRegisteredSoftWraps().size());
@@ -469,7 +467,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
" public String s = \"this is a long string literal that is expected to be soft-wrapped into multiple visual lines\";\n" +
"}";
init(250, text);
init(30, text);
myEditor.getCaretModel().moveToOffset(text.indexOf("}") - 1);
List<? extends SoftWrap> softWraps = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
@@ -510,7 +508,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
" public String s = \"this is a long string literal that is expected to be soft-wrapped into multiple visual lines\"; \n" +
"}";
init(250, text);
init(30, text);
myEditor.getCaretModel().moveToOffset(text.indexOf("\n") + 1);
List<? extends SoftWrap> softWraps = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
@@ -574,7 +572,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"this is line 4\n" +
"this is line 5";
init(50, text);
init(50, text, 7);
VisualPosition changePosition = new VisualPosition(1, 0);
myEditor.getCaretModel().moveToVisualPosition(changePosition);
@@ -635,7 +633,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"3. just a line that is long enough to be soft wrapped\n" +
"4. just a line that is long enough to be soft wrapped";
init(100, text);
init(15, text);
Document document = myEditor.getDocument();
int start = document.getLineStartOffset(1);
int end = document.getLineEndOffset(1) + 1;
@@ -663,7 +661,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"2. just a line that is long enough to be soft wrapped\n" +
"3. just a line that is long enough to be soft wrapped\n" +
"4. just a line that is long enough to be soft wrapped";
init(100, text);
init(15, text);
CaretModel caretModel = myEditor.getCaretModel();
caretModel.moveToOffset(text.indexOf("2.") + 2);
@@ -685,7 +683,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
" this is a string that starts with white space and is long enough to be soft-wrapped\n" +
" this is a 'prefix' text before collapsed multi-line folding that is long enough to be soft-wrapped first fold line\n" +
"second fold line";
init(200, text);
init(30, text);
addCollapsedFoldRegion(text.indexOf("first fold line"), text.length(), "...");
@@ -715,7 +713,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"\n" +
"class Test {\n" +
"}";
init(300, text);
init(40, text);
final int foldStartOffset = "import".length() + 1;
int foldEndOffset = text.indexOf("class") - 2;
@@ -749,7 +747,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"\n" +
"class Test {\n" +
"}";
init(300, text);
init(40, text);
final int foldStartOffset = text.indexOf("java.util.Collections");
final int foldEndOffset = text.indexOf("class") - 2;
@@ -768,7 +766,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"222\n" +
"33333333 33333333333333333333333333333333\n" +
"444";
init(100, text);
init(15, text);
assertEquals(new LogicalPosition(3, 0), myEditor.visualToLogicalPosition(new VisualPosition(4, 0)));
}
@@ -781,7 +779,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"444 55\n" +
"666 77";
init(100, text);
init(15, text);
int foldStart = text.indexOf("5");
int foldEnd = text.indexOf("7");
@@ -798,7 +796,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
public void testNoWrapAtFirstNonWsSymbolWithCustomIndent() throws IOException {
String text =
" 1111111111111111111111111111111";
init(70, text);
init(10, text);
getEditor().getSettings().setCustomSoftWrapIndent(0);
getEditor().getSettings().setUseCustomSoftWrapIndent(true);
int textLength = getEditor().getDocument().getTextLength();
@@ -814,7 +812,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
// Inspired by IDEA-76353. The point is that we need to consider cached information about tab symbols width during logical
// position to offset mapping
String text = "\t test";
init(100, text);
init(15, text);
((EditorImpl)myEditor).setPrefixTextAndAttributes(" ", new TextAttributes());
myEditor.getCaretModel().moveToOffset(text.length());
}
@@ -827,7 +825,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"\t third line";
// Make soft wraps to build a document info cache.
init(300, text);
init(40, text);
// Modify document while soft wraps processing is off.
final EditorSettings settings = getEditor().getSettings();
@@ -856,7 +854,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"\t<caret> my text";
// Build soft wraps cache.
init(300, text);
init(40, text);
VisualPosition caretPositionBefore = getEditor().getCaretModel().getVisualPosition();
@@ -871,12 +869,86 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
getEditor().getCaretModel().getVisualPosition()
);
}
private void init(final int visibleWidth, @NotNull String fileText) throws IOException {
init(visibleWidth, fileText, TestFileType.TEXT);
public void testNoPreliminarySoftWrapAtLineEnd() throws IOException {
// We used to make soft wrap when the string was couple of visual columns before the right screen edge even if it could
// be completely shown.
init(37, "a b c", 7);
assertEmpty(getSoftWrapModel().getRegisteredSoftWraps());
}
public void testNoPreliminarySoftWrapBeforeFoldingAtLineEnd() throws IOException {
final String text = "a b c test";
init(50, text, 7);
addCollapsedFoldRegion(text.indexOf("t"), text.length(), ".");
assertEmpty(getSoftWrapModel().getRegisteredSoftWraps());
}
public void testMultiLineFoldRegionBeforeWrapPosition() throws IOException {
final String text =
"package org.denis;\n" +
"\n" +
"\n" +
"public class BrokenAlignment {\n" +
"\n" +
" void method1(int a) {\n" +
" }\n" +
"\n" +
" Object method2(Object ... data) {\n" +
" return new Runnable() {\n" +
" public void run() {\n" +
" System.out.println();\n" +
" }\n" +
" };\n" +
" }\n" +
"\n" +
"}";
init(511, text, TestFileType.JAVA, 10);
addCollapsedFoldRegion(text.indexOf("new Runnable"), text.indexOf("System"), "Runnable() { ");
int start = text.indexOf("System");
start = text.indexOf("\n", start);
int end = text.indexOf(';', start);
addCollapsedFoldRegion(start, end, " }");
final List<? extends SoftWrap> wraps = getSoftWrapModel().getRegisteredSoftWraps();
assertEquals(1, wraps.size());
assertEquals(start, wraps.get(0).getStart());
assertEquals(myEditor.offsetToVisualPosition(start), myEditor.offsetToVisualPosition(start + 1));
assertEquals(myEditor.offsetToVisualPosition(start).line, myEditor.offsetToVisualPosition(end).line);
}
private void init(final int visibleWidth, @NotNull String fileText, @NotNull TestFileType fileType) throws IOException {
public void testEnsureBeforeSoftWrapSignIsVisible() throws IOException {
final String text = "a.b.c.d";
init(43, text, 7);
checkSoftWraps(text.indexOf('c') + 1);
}
public void testWrapAfterCollapsedFoldRegion() throws IOException {
final String text =
"this is a long text to fold more";
init(12, text);
int start = text.indexOf("long");
int end = text.indexOf("more");
addCollapsedFoldRegion(start, end, "placeholder which is long enough to be wrapped");
checkSoftWraps(start, end);
}
private void init(final int visibleWidthInColumns, @NotNull String fileText) throws IOException {
int symbolWidthInPixels = 7;
init(visibleWidthInColumns * symbolWidthInPixels, fileText, symbolWidthInPixels);
}
private void init(final int visibleWidth, @NotNull String fileText, int symbolWidth) throws IOException {
init(visibleWidth, fileText, TestFileType.TEXT, symbolWidth);
}
private void init(final int visibleWidth, @NotNull String fileText, @NotNull TestFileType fileType, final int symbolWidth) throws IOException {
init(fileText, fileType);
myEditor.getSettings().setUseSoftWraps(true);
SoftWrapModelImpl model = (SoftWrapModelImpl)myEditor.getSoftWrapModel();
@@ -889,9 +961,27 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
return visibleWidth;
}
});
if (symbolWidth > 0) {
applianceManager.setRepresentationHelper(new DefaultEditorTextRepresentationHelper(myEditor) {
@Override
public int charWidth(char c, int fontType) {
return symbolWidth;
}
});
}
applianceManager.registerSoftWrapIfNecessary();
}
private static void checkSoftWraps(int... startOffsets) {
final List<? extends SoftWrap> softWraps = getSoftWrapModel().getRegisteredSoftWraps();
assertEquals("soft wraps number", startOffsets.length, softWraps.size());
for (int i = 0; i < startOffsets.length; i++) {
assertEquals(startOffsets[i], softWraps.get(i).getStart());
}
}
private static SoftWrapModelImpl getSoftWrapModel() {
return (SoftWrapModelImpl)myEditor.getSoftWrapModel();
}