mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-56359 Soft wrap: commas could append previous symbol when wrapping
1. Added mini unit test framework for soft wrap appliance tests; 2. Corrected soft wrap appliance algorithm in order to avoid wrapping before comma;
This commit is contained in:
+2
-4
@@ -19,8 +19,6 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since Jul 27, 2010 4:06:27 PM
|
||||
@@ -39,7 +37,7 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen
|
||||
}
|
||||
|
||||
@Override
|
||||
public int textWidth(@NotNull CharSequence text, int start, int end, int x) {
|
||||
return EditorUtil.textWidth(myEditor, text, start, end, Font.PLAIN, x);
|
||||
public int textWidth(@NotNull CharSequence text, int start, int end, int fontType, int x) {
|
||||
return EditorUtil.textWidth(myEditor, text, start, end, fontType, x);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -48,11 +48,12 @@ public interface EditorTextRepresentationHelper {
|
||||
* <b>Note:</b> target region is allows to contain line feeds, the width is calculated as a difference between <code>'x'</code>
|
||||
* coordinates of the last and first symbols.
|
||||
*
|
||||
* @param text target text holder
|
||||
* @param start start offset of the target text sub-sequence (inclusive)
|
||||
* @param end end offset of the target text sub-sequence (exclusive)
|
||||
* @param x <code>'x'</code> offset from the visual line start
|
||||
* @return width in pixels necessary for the target text sub-sequence representation
|
||||
* @param text target text holder
|
||||
* @param start start offset of the target text sub-sequence (inclusive)
|
||||
* @param end end offset of the target text sub-sequence (exclusive)
|
||||
* @param fontType font type used for the given substring representation
|
||||
* @param x <code>'x'</code> offset from the visual line start
|
||||
* @return width in pixels necessary for the target text sub-sequence representation
|
||||
*/
|
||||
int textWidth(@NotNull CharSequence text, int start, int end, int x);
|
||||
int textWidth(@NotNull CharSequence text, int start, int end, int fontType, int x);
|
||||
}
|
||||
|
||||
@@ -58,10 +58,14 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
|
||||
}
|
||||
|
||||
public SoftWrapModelImpl(@NotNull final EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter) {
|
||||
this(editor, storage, painter, new DefaultEditorTextRepresentationHelper(editor));
|
||||
}
|
||||
|
||||
public SoftWrapModelImpl(@NotNull final EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter,
|
||||
EditorTextRepresentationHelper representationHelper) {
|
||||
this(
|
||||
editor, storage, painter, new DefaultSoftWrapApplianceManager(storage, editor, painter),
|
||||
new SoftWrapDataMapper(editor, storage, new DefaultEditorTextRepresentationHelper(editor)),
|
||||
new SoftWrapDocumentChangeManager(editor, storage)
|
||||
editor, storage, painter, new DefaultSoftWrapApplianceManager(storage, editor, painter, representationHelper),
|
||||
new SoftWrapDataMapper(editor, storage, representationHelper), new SoftWrapDocumentChangeManager(editor, storage)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+21
-10
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.VisualPosition;
|
||||
import com.intellij.openapi.editor.actions.EditorActionUtil;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -103,16 +104,22 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
|
||||
|
||||
private final TIntHashSet myProcessedLogicalLines = new TIntHashSet();
|
||||
|
||||
private final SoftWrapsStorage myStorage;
|
||||
private final EditorEx myEditor;
|
||||
private final SoftWrapPainter myPainter;
|
||||
private final EditorTextRepresentationHelper myTextRepresentationHelper;
|
||||
private final SoftWrapsStorage myStorage;
|
||||
private final EditorEx myEditor;
|
||||
private final SoftWrapPainter myPainter;
|
||||
|
||||
private int myVisibleAreaWidth;
|
||||
|
||||
public DefaultSoftWrapApplianceManager(SoftWrapsStorage storage, EditorEx editor, SoftWrapPainter painter) {
|
||||
public DefaultSoftWrapApplianceManager(SoftWrapsStorage storage,
|
||||
EditorEx editor,
|
||||
SoftWrapPainter painter,
|
||||
EditorTextRepresentationHelper textRepresentationHelper)
|
||||
{
|
||||
myStorage = storage;
|
||||
myEditor = editor;
|
||||
myPainter = painter;
|
||||
myTextRepresentationHelper = textRepresentationHelper;
|
||||
init(editor.getDocument());
|
||||
}
|
||||
|
||||
@@ -215,10 +222,11 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
|
||||
// Find offsets where soft wraps should be applied for the logical line in case of no indent usage.
|
||||
int x = myPainter.getMinDrawingWidth(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
|
||||
int prevSoftWrapOffset = start;
|
||||
CharBuffer buffer = CharBuffer.wrap(text);
|
||||
for (int i = start; i < end; i++) {
|
||||
int symbolWidth = EditorUtil.textWidth(myEditor, CharBuffer.wrap(text), i, i + 1, fontType, x);
|
||||
int symbolWidth = myTextRepresentationHelper.textWidth(buffer, i, i + 1, fontType, x);
|
||||
if (x + symbolWidth >= myVisibleAreaWidth) {
|
||||
int offset = calculateSoftWrapOffset(text, i - 1, prevSoftWrapOffset, end);
|
||||
int offset = calculateSoftWrapOffset(text, i, prevSoftWrapOffset, end);
|
||||
if (offset >= end || offset <= prevSoftWrapOffset) {
|
||||
// There is no way to insert soft wrap.
|
||||
return result;
|
||||
@@ -272,8 +280,8 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
|
||||
for (int i = preferred; i > min; i--) {
|
||||
char c = text[i];
|
||||
|
||||
if (i < preferred && WHITE_SPACES.contains(c)) {
|
||||
return i + 1;
|
||||
if (WHITE_SPACES.contains(c)) {
|
||||
return i < preferred ? i + 1 : i;
|
||||
}
|
||||
|
||||
// Don't wrap on the non-id symbol preceded by another non-id symbol. E.g. consider that we have a statement
|
||||
@@ -281,8 +289,11 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
|
||||
if (i > min + 1 && !isIdSymbol(c) && !isIdSymbol(text[i - 1])) {
|
||||
continue;
|
||||
}
|
||||
if ((i < preferred) && SPECIAL_SYMBOLS_TO_WRAP_AFTER.contains(c)) {
|
||||
return i + 1;
|
||||
if (SPECIAL_SYMBOLS_TO_WRAP_AFTER.contains(c)) {
|
||||
if (i < preferred) {
|
||||
return i + 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (SPECIAL_SYMBOLS_TO_WRAP_BEFORE.contains(c) || WHITE_SPACES.contains(c)) {
|
||||
return i;
|
||||
|
||||
+5
-4
@@ -23,6 +23,7 @@ import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -264,7 +265,7 @@ public class SoftWrapDataMapper {
|
||||
int i = CharArrayUtil.shiftBackwardUntil(text, region.getEndOffset() - 1, "\n");
|
||||
// Process multi-line folding.
|
||||
if (i >= region.getStartOffset()) {
|
||||
afterFolding.x = myTextRepresentationHelper.textWidth(text, i + 1, region.getEndOffset(), 0);
|
||||
afterFolding.x = myTextRepresentationHelper.textWidth(text, i + 1, region.getEndOffset(), Font.PLAIN, 0);
|
||||
afterFolding.logicalColumn = myTextRepresentationHelper.toVisualColumnSymbolsNumber(text, i + 1, region.getEndOffset(), 0);
|
||||
afterFolding.softWrapLinesBefore += afterFolding.softWrapLinesCurrent;
|
||||
afterFolding.softWrapLinesCurrent = 0;
|
||||
@@ -274,7 +275,7 @@ public class SoftWrapDataMapper {
|
||||
}
|
||||
// Process single-line folding
|
||||
else {
|
||||
int width = myTextRepresentationHelper.textWidth(text, region.getStartOffset(), region.getEndOffset(), context.x);
|
||||
int width = myTextRepresentationHelper.textWidth(text, region.getStartOffset(), region.getEndOffset(), Font.PLAIN, context.x);
|
||||
int logicalColumnInc = myTextRepresentationHelper.toVisualColumnSymbolsNumber(
|
||||
text, region.getStartOffset(), region.getEndOffset(), context.x
|
||||
);
|
||||
@@ -342,7 +343,7 @@ public class SoftWrapDataMapper {
|
||||
|
||||
// Update state to the offset that corresponds to the same logical line that was used last time.
|
||||
if (currentLogicalLine == lastUsedLogicalLine) {
|
||||
int width = myTextRepresentationHelper.textWidth(text, result.offset, newOffset, result.x);
|
||||
int width = myTextRepresentationHelper.textWidth(text, result.offset, newOffset, Font.PLAIN, result.x);
|
||||
int columnDiff = myTextRepresentationHelper.toVisualColumnSymbolsNumber(text, result.offset, newOffset, result.x);
|
||||
result.x += width;
|
||||
result.logicalColumn += columnDiff;
|
||||
@@ -354,7 +355,7 @@ public class SoftWrapDataMapper {
|
||||
result.logicalLine += lineDiff;
|
||||
result.visualLine += lineDiff;
|
||||
int startLineOffset = document.getLineStartOffset(currentLogicalLine);
|
||||
int newX = myTextRepresentationHelper.textWidth(text, startLineOffset, newOffset, result.x);
|
||||
int newX = myTextRepresentationHelper.textWidth(text, startLineOffset, newOffset, Font.PLAIN, result.x);
|
||||
result.visualColumn = myTextRepresentationHelper.toVisualColumnSymbolsNumber(text, startLineOffset, newOffset, 0);
|
||||
result.x = newX;
|
||||
result.logicalColumn = result.visualColumn;
|
||||
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.editor.impl.softwrap;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.ScrollingModel;
|
||||
import com.intellij.openapi.editor.event.DocumentListener;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jmock.Expectations;
|
||||
import org.junit.Test;
|
||||
import org.junit.Before;
|
||||
import org.junit.After;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.lib.legacy.ClassImposteriser;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 08/04/2010
|
||||
*/
|
||||
public class DefaultSoftWrapApplianceManagerTest {
|
||||
|
||||
private static final String EDGE_MARKER = "<EDGE>";
|
||||
private static final String WRAP_MARKER = "<WRAP>";
|
||||
private static final int SOFT_WRAP_DRAWING_SIZE = 11;
|
||||
|
||||
private DefaultSoftWrapApplianceManager myManager;
|
||||
private Mockery myMockery;
|
||||
private SoftWrapsStorage myStorage;
|
||||
private EditorEx myEditor;
|
||||
private SoftWrapPainter myPainter;
|
||||
private Document myDocument;
|
||||
private ScrollingModel myScrollingModel;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
myMockery = new JUnit4Mockery() {{
|
||||
setImposteriser(ClassImposteriser.INSTANCE);
|
||||
}};
|
||||
myStorage = myMockery.mock(SoftWrapsStorage.class);
|
||||
myEditor = myMockery.mock(EditorEx.class);
|
||||
myPainter = myMockery.mock(SoftWrapPainter.class);
|
||||
myDocument = myMockery.mock(Document.class);
|
||||
myScrollingModel = myMockery.mock(ScrollingModel.class);
|
||||
|
||||
myMockery.checking(new Expectations() {{
|
||||
// Editor.
|
||||
allowing(myEditor).isViewer(); will(returnValue(false));
|
||||
|
||||
// Document.
|
||||
allowing(myEditor).getDocument(); will(returnValue(myDocument));
|
||||
allowing(myDocument).addDocumentListener(with(any(DocumentListener.class)));
|
||||
allowing(myDocument).getLineNumber(with(any(int.class))); will(returnValue(0)); // Expecting to work only with single lines here.
|
||||
allowing(myDocument).getLineStartOffset(0); will(returnValue(0)); // Expecting to work only with single lines here.
|
||||
allowing(myDocument).isWritable(); will(returnValue(true));
|
||||
|
||||
// Scrolling model.
|
||||
allowing(myEditor).getScrollingModel(); will(returnValue(myScrollingModel));
|
||||
|
||||
// Storage.
|
||||
allowing(myStorage).removeAll();
|
||||
|
||||
// Soft wrap drawings.
|
||||
allowing(myPainter).getMinDrawingWidth(with(any(SoftWrapDrawingType.class))); will(returnValue(SOFT_WRAP_DRAWING_SIZE));
|
||||
}});
|
||||
|
||||
myManager = new DefaultSoftWrapApplianceManager(myStorage, myEditor, myPainter, new MockEditorTextRepresentationHelper());
|
||||
}
|
||||
|
||||
@After
|
||||
public void checkExpectations() {
|
||||
myMockery.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void commaNotSeparated() {
|
||||
String document =
|
||||
"void method(String <WRAP>p1<EDGE>, String p2) {}";
|
||||
doTest(document);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrapOnExceedingWhiteSpace() {
|
||||
String document =
|
||||
"void method(String p1,<WRAP><EDGE> String p2) {}";
|
||||
doTest(document);
|
||||
}
|
||||
|
||||
private void doTest(final String document) {
|
||||
final Context context = new Context(document);
|
||||
context.init();
|
||||
myMockery.checking(new Expectations() {{
|
||||
allowing(myScrollingModel).getVisibleArea(); will(returnValue(new Rectangle(0, 0, context.visualWidth, Integer.MAX_VALUE)));
|
||||
allowing(myDocument).getLineEndOffset(0); will(returnValue(context.document.length()));
|
||||
}});
|
||||
char[] documentChars = context.document.toCharArray();
|
||||
myManager.registerSoftWrapIfNecessary(documentChars, 0, documentChars.length, 0, Font.PLAIN);
|
||||
}
|
||||
|
||||
private static TextChangeImpl createSoftWrap(int offset, int indent) {
|
||||
String text = "\n" + StringUtil.join(Collections.nCopies(indent, " "), "");
|
||||
return new TextChangeImpl(text, offset, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class for parsing and initialising test data.
|
||||
* <p/>
|
||||
* <b>Note:</b> this class is line-oriented, i.e. it assumes that target document doesn't contain line feeds.
|
||||
*/
|
||||
private class Context {
|
||||
|
||||
private final StringBuilder buffer = new StringBuilder();
|
||||
private final String rawDocument;
|
||||
|
||||
private String document;
|
||||
private int visualWidth;
|
||||
private int index;
|
||||
private int wrapIndex;
|
||||
private int edgeIndex;
|
||||
|
||||
Context(String rawDocument) {
|
||||
if (rawDocument.contains("\n")) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Don't expect to test multi-line documents but the one is detected: '%s'", rawDocument)
|
||||
);
|
||||
}
|
||||
this.rawDocument = rawDocument;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
wrapIndex = rawDocument.indexOf(WRAP_MARKER);
|
||||
edgeIndex = rawDocument.indexOf(EDGE_MARKER);
|
||||
while (wrapIndex >= 0 || edgeIndex >= 0) {
|
||||
if (wrapIndex >= 0 && edgeIndex >= 0) {
|
||||
if (wrapIndex < edgeIndex) {
|
||||
processWrap();
|
||||
}
|
||||
else {
|
||||
processEdge();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (wrapIndex >= 0) {
|
||||
processWrap();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (edgeIndex >= 0) {
|
||||
processEdge();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
buffer.append(rawDocument.substring(index));
|
||||
assert visualWidth > 0;
|
||||
document = buffer.toString();
|
||||
}
|
||||
|
||||
private void processWrap() {
|
||||
buffer.append(rawDocument.substring(index, wrapIndex));
|
||||
myMockery.checking(new Expectations() {{
|
||||
one(myStorage).storeOrReplace(createSoftWrap(buffer.length(), 0));
|
||||
}});
|
||||
index = wrapIndex + WRAP_MARKER.length();
|
||||
wrapIndex = rawDocument.indexOf(WRAP_MARKER, index);
|
||||
}
|
||||
|
||||
private void processEdge() {
|
||||
if (visualWidth > 0) {
|
||||
throw new IllegalArgumentException(String.format("More than one visual edge sign found at the document '%s'", rawDocument));
|
||||
}
|
||||
buffer.append(rawDocument.substring(index, edgeIndex));
|
||||
visualWidth = (buffer.length() * MockEditorTextRepresentationHelper.DEFAULT_SPACE_SIZE_IN_PIXELS) + SOFT_WRAP_DRAWING_SIZE + 1;
|
||||
index = edgeIndex + EDGE_MARKER.length();
|
||||
edgeIndex = rawDocument.indexOf(EDGE_MARKER, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.editor.impl.softwrap;
|
||||
|
||||
import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since Aug 5, 2010 9:18:15 AM
|
||||
*/
|
||||
public class MockEditorTextRepresentationHelper implements EditorTextRepresentationHelper {
|
||||
|
||||
public static final int DEFAULT_TAB_SIZE_IN_COLUMNS = 4;
|
||||
public static final int DEFAULT_SPACE_SIZE_IN_PIXELS = 7;
|
||||
|
||||
private final int mySpaceSizeInPixels;
|
||||
private final int myTabSizeInColumns;
|
||||
|
||||
public MockEditorTextRepresentationHelper() {
|
||||
this(DEFAULT_SPACE_SIZE_IN_PIXELS, DEFAULT_TAB_SIZE_IN_COLUMNS);
|
||||
}
|
||||
|
||||
MockEditorTextRepresentationHelper(int spaceSizeInPixels, int tabSizeInColumns) {
|
||||
mySpaceSizeInPixels = spaceSizeInPixels;
|
||||
myTabSizeInColumns = tabSizeInColumns;
|
||||
}
|
||||
|
||||
public int toVisualColumnSymbolsNumber(char c, int x) {
|
||||
return toVisualColumnSymbolsNumber(new String(new char[] {c}), 0, 1, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int toVisualColumnSymbolsNumber(@NotNull CharSequence text, int start, int end, int x) {
|
||||
int result = 0;
|
||||
for (int i = start; i < end; i++) {
|
||||
int width = charWidth(text.charAt(i), x);
|
||||
result += width / mySpaceSizeInPixels;
|
||||
if (width % mySpaceSizeInPixels > 0) {
|
||||
result++;
|
||||
}
|
||||
x += width;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int textWidth(@NotNull CharSequence text, int start, int end, int fontType, int x) {
|
||||
int result = 0;
|
||||
for (int i = start; i < end; i++) {
|
||||
char c = text.charAt(i);
|
||||
switch (c) {
|
||||
case '\n': result = 0; break;
|
||||
default: result += charWidth(c, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public int charWidth(char c, int x) {
|
||||
if (c == '\t') {
|
||||
int tabWidth = mySpaceSizeInPixels * myTabSizeInColumns;
|
||||
int tabsNumber = x / tabWidth;
|
||||
return (tabsNumber + 1) * tabWidth - x;
|
||||
}
|
||||
else {
|
||||
return mySpaceSizeInPixels;
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-58
@@ -5,11 +5,9 @@ import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.FoldingModelEx;
|
||||
import com.intellij.openapi.editor.ex.SoftWrapModelEx;
|
||||
import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
@@ -21,6 +19,7 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -207,7 +206,7 @@ public class SoftWrapDataMapperTest {
|
||||
allowing(painter).getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP); will(returnValue(SOFT_WRAP_DRAWING_WIDTH));
|
||||
}});
|
||||
|
||||
myRepresentationHelper = new MockEditorTextRepresentationHelper();
|
||||
myRepresentationHelper = new MockEditorTextRepresentationHelper(SPACE_SIZE, TAB_SIZE);
|
||||
|
||||
myAdjuster = new SoftWrapDataMapper(myEditor, myStorage, myRepresentationHelper/*, new MockFontTypeProvider()*/);
|
||||
}
|
||||
@@ -398,7 +397,7 @@ public class SoftWrapDataMapperTest {
|
||||
if (text.charAt(i) == '\n') {
|
||||
break;
|
||||
}
|
||||
result += myRepresentationHelper.textWidth(text, i, i + 1, 0);
|
||||
result += myRepresentationHelper.textWidth(text, i, i + 1, Font.PLAIN, 0);
|
||||
}
|
||||
result += SOFT_WRAP_DRAWING_WIDTH;
|
||||
return result;
|
||||
@@ -493,8 +492,6 @@ public class SoftWrapDataMapperTest {
|
||||
// We don't want to perform the check for logical positions that correspond to the folded space because all of them relate to
|
||||
// the same logical position of the folding start.
|
||||
if (!data.foldedSpace && !data.insideTab && !equals(data.logical, actualLogicalByVisual)) {
|
||||
//TODO den remove
|
||||
myAdjuster.visualToLogical(data.visual);
|
||||
throw new AssertionError(
|
||||
String.format("Detected unmatched logical position by visual (%s). Expected: '%s', actual: '%s'. Calculation was performed "
|
||||
+ "against soft wrap-unaware logical: '%s'",
|
||||
@@ -507,8 +504,6 @@ public class SoftWrapDataMapperTest {
|
||||
// We don't to perform the check for the data that points to soft wrap location here. The reason is that it shares offset
|
||||
// with the first document symbol after soft wrap, hence, examination always fails.
|
||||
if (!data.virtualSpace && !data.insideTab && !equals(data.logical, actualLogicalByOffset)) {
|
||||
//TODO den remove
|
||||
myAdjuster.offsetToLogicalPosition(data.offset);
|
||||
throw new AssertionError(
|
||||
String.format("Detected unmatched logical position by offset. Expected: '%s', actual: '%s'. Calculation was performed "
|
||||
+ "against offset: '%d' and soft wrap-unaware logical: '%s'",
|
||||
@@ -698,7 +693,7 @@ public class SoftWrapDataMapperTest {
|
||||
}
|
||||
else if (c == '\t') {
|
||||
int tabWidthInColumns = myRepresentationHelper.toVisualColumnSymbolsNumber(c, x);
|
||||
x += MockEditorTextRepresentationHelper.charWidth(c, x);
|
||||
x += myRepresentationHelper.charWidth(c, x);
|
||||
|
||||
// There is a possible case that single tabulation symbols is shown in more than one visual column at IntelliJ editor.
|
||||
// We store data entry only for the first tab column without 'inside tab' flag then.
|
||||
@@ -715,7 +710,7 @@ public class SoftWrapDataMapperTest {
|
||||
} else {
|
||||
logicalColumn++;
|
||||
offset++;
|
||||
x += MockEditorTextRepresentationHelper.charWidth(c, x);
|
||||
x += myRepresentationHelper.charWidth(c, x);
|
||||
foldingColumnDiff--;
|
||||
}
|
||||
return;
|
||||
@@ -748,7 +743,7 @@ public class SoftWrapDataMapperTest {
|
||||
visualColumn++;
|
||||
softWrapColumnDiff++;
|
||||
softWrapSymbolsOnCurrentVisualLine++;
|
||||
x += MockEditorTextRepresentationHelper.charWidth(c, x);
|
||||
x += myRepresentationHelper.charWidth(c, x);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -769,7 +764,7 @@ public class SoftWrapDataMapperTest {
|
||||
}
|
||||
else if (c == '\t') {
|
||||
int tabWidthInColumns = myRepresentationHelper.toVisualColumnSymbolsNumber(c, x);
|
||||
x += MockEditorTextRepresentationHelper.charWidth(c, x);
|
||||
x += myRepresentationHelper.charWidth(c, x);
|
||||
|
||||
// There is a possible case that single tabulation symbols is shown in more than one visual column at IntelliJ editor.
|
||||
// We store data entry only for the first tab column without 'inside tab' flag then.
|
||||
@@ -789,7 +784,7 @@ public class SoftWrapDataMapperTest {
|
||||
visualColumn++;
|
||||
logicalColumn++;
|
||||
offset++;
|
||||
x += MockEditorTextRepresentationHelper.charWidth(c, x);
|
||||
x += myRepresentationHelper.charWidth(c, x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -838,51 +833,6 @@ public class SoftWrapDataMapperTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static class MockEditorTextRepresentationHelper implements EditorTextRepresentationHelper {
|
||||
|
||||
public int toVisualColumnSymbolsNumber(char c, int x) {
|
||||
return toVisualColumnSymbolsNumber(new String(new char[] {c}), 0, 1, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int toVisualColumnSymbolsNumber(@NotNull CharSequence text, int start, int end, int x) {
|
||||
int result = 0;
|
||||
for (int i = start; i < end; i++) {
|
||||
int width = charWidth(text.charAt(i), x);
|
||||
result += width / SPACE_SIZE;
|
||||
if (width % SPACE_SIZE > 0) {
|
||||
result++;
|
||||
}
|
||||
x += width;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int textWidth(@NotNull CharSequence text, int start, int end, int x) {
|
||||
int result = 0;
|
||||
for (int i = start; i < end; i++) {
|
||||
char c = text.charAt(i);
|
||||
switch (c) {
|
||||
case '\n': result = 0; break;
|
||||
default: result += charWidth(c, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int charWidth(char c, int x) {
|
||||
if (c == '\t') {
|
||||
int tabWidth = SPACE_SIZE * TAB_SIZE;
|
||||
int tabsNumber = x / tabWidth;
|
||||
return (tabsNumber + 1) * tabWidth - x;
|
||||
}
|
||||
else {
|
||||
return SPACE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//private static class MockFontTypeProvider implements SoftWrapDataMapper.FontTypeProvider {
|
||||
// @Override
|
||||
// public void init(int start) {
|
||||
|
||||
Reference in New Issue
Block a user