mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
editor new rendering: limit memory used by text layout cache
This commit is contained in:
+5
-5
@@ -73,7 +73,7 @@ class EditorCoordinateMapper {
|
||||
int visualLine = offsetToVisualLine(offset, beforeSoftWrap);
|
||||
int maxVisualColumn = 0;
|
||||
int maxLogicalColumn = 0;
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, offset, beforeSoftWrap, false)) {
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, offset, beforeSoftWrap, null)) {
|
||||
if (!pos.leansForward && offset == fragment.getVisualLineStartOffset()) {
|
||||
return new VisualPosition(visualLine, fragment.getStartVisualColumn());
|
||||
}
|
||||
@@ -125,7 +125,7 @@ class EditorCoordinateMapper {
|
||||
int maxVisualColumn = 0;
|
||||
int maxLogicalColumn = 0;
|
||||
int maxOffset = offset;
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, offset, false, false)) {
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, offset, false, null)) {
|
||||
int minColumn = fragment.getStartVisualColumn();
|
||||
int maxColumn = fragment.getEndVisualColumn();
|
||||
if (column < minColumn || column == minColumn && !pos.leansRight) {
|
||||
@@ -240,7 +240,7 @@ class EditorCoordinateMapper {
|
||||
if (visualLine < myView.getEditor().getVisibleLineCount()) {
|
||||
int visualLineStartOffset = visualLineToOffset(visualLine);
|
||||
int maxOffset = 0;
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, visualLineStartOffset, false, false)) {
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, visualLineStartOffset, false, null)) {
|
||||
if (p.x <= fragment.getStartX()) {
|
||||
int markerWidth = myView.getEditor().getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
float indent = fragment.getStartX() - markerWidth;
|
||||
@@ -286,7 +286,7 @@ class EditorCoordinateMapper {
|
||||
if (visualLine < myView.getEditor().getVisibleLineCount()) {
|
||||
int visualLineStartOffset = visualLineToOffset(visualLine);
|
||||
int maxOffset = 0;
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, visualLineStartOffset, false, false)) {
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, visualLineStartOffset, false, null)) {
|
||||
if (column < fragment.getStartVisualColumn()) {
|
||||
break;
|
||||
}
|
||||
@@ -317,7 +317,7 @@ class EditorCoordinateMapper {
|
||||
float x = getStartX(logicalLine);
|
||||
if (myDocument.getTextLength() > 0) {
|
||||
boolean firstFragment = true;
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, offset, beforeSoftWrap, false)) {
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, offset, beforeSoftWrap, null)) {
|
||||
if (firstFragment && offset == visualLineStartOffset && !leanTowardsLargerOffsets) {
|
||||
x = fragment.getStartX();
|
||||
break;
|
||||
|
||||
@@ -584,7 +584,7 @@ class EditorPainter implements TextDrawingCallback {
|
||||
}
|
||||
}
|
||||
else {
|
||||
int maxWidth = myView.getMaxWidthInLineRange(startPosition.line, endPosition.line, false) - 1;
|
||||
int maxWidth = myView.getMaxWidthInLineRange(startPosition.line, endPosition.line, null) - 1;
|
||||
TFloatArrayList leadingRanges = adjustedLogicalRangeToVisualRanges(startOffset,
|
||||
myView.visualPositionToOffset(new VisualPosition(
|
||||
startPosition.line, Integer.MAX_VALUE, true)));
|
||||
@@ -691,7 +691,7 @@ class EditorPainter implements TextDrawingCallback {
|
||||
private TFloatArrayList logicalRangeToVisualRanges(int startOffset, int endOffset) {
|
||||
assert startOffset <= endOffset;
|
||||
TFloatArrayList result = new TFloatArrayList();
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, startOffset, false, false)) {
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, startOffset, false, null)) {
|
||||
int minOffset = fragment.getMinOffset();
|
||||
int maxOffset = fragment.getMaxOffset();
|
||||
if (startOffset == endOffset) {
|
||||
@@ -772,7 +772,7 @@ class EditorPainter implements TextDrawingCallback {
|
||||
int targetVisualColumn = caret.getVisualPosition().column;
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView,
|
||||
caret.getVisualLineStart(),
|
||||
false, false)) {
|
||||
false, null)) {
|
||||
int startVisualColumn = fragment.getStartVisualColumn();
|
||||
int endVisualColumn = fragment.getEndVisualColumn();
|
||||
if (startVisualColumn < targetVisualColumn && endVisualColumn > targetVisualColumn ||
|
||||
@@ -810,7 +810,7 @@ class EditorPainter implements TextDrawingCallback {
|
||||
int prevEndOffset = -1;
|
||||
boolean firstFragment = true;
|
||||
int maxColumn = 0;
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, offset, false, false)) {
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, offset, false, null)) {
|
||||
int fragmentStartOffset = fragment.getStartOffset();
|
||||
int start = fragmentStartOffset;
|
||||
int end = fragment.getEndOffset();
|
||||
|
||||
+21
-6
@@ -29,6 +29,7 @@ import com.intellij.openapi.editor.impl.EditorImpl;
|
||||
import com.intellij.openapi.editor.impl.softwrap.mapping.IncrementalCacheUpdateEvent;
|
||||
import com.intellij.openapi.editor.impl.softwrap.mapping.SoftWrapAwareDocumentParsingListenerAdapter;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import gnu.trove.TIntArrayList;
|
||||
@@ -43,14 +44,15 @@ import java.util.List;
|
||||
* Calculates width (in pixels) of editor contents.
|
||||
*/
|
||||
class EditorSizeManager implements PrioritizedDocumentListener, Disposable, FoldingListener {
|
||||
private static final int UNKNOWN_WIDTH = -1;
|
||||
private static final int UNKNOWN_WIDTH = Integer.MAX_VALUE;
|
||||
|
||||
private final EditorView myView;
|
||||
private final EditorImpl myEditor;
|
||||
private final DocumentEx myDocument;
|
||||
|
||||
private final TIntArrayList myLineWidths = new TIntArrayList(); // cached widths of visual lines (in pixels)
|
||||
// UNKNOWN_WIDTH(-1) means no value
|
||||
// negative value means an estimated (not precise) width
|
||||
// UNKNOWN_WIDTH(Integer.MAX_VALUE) means no value
|
||||
private int myWidthInPixels;
|
||||
|
||||
private int myMaxLineWithExtensionWidth;
|
||||
@@ -175,7 +177,14 @@ class EditorSizeManager implements PrioritizedDocumentListener, Disposable, Fold
|
||||
for (int i = 0; i < lineCount; i++) {
|
||||
int width = myLineWidths.get(i);
|
||||
if (width == UNKNOWN_WIDTH) {
|
||||
width = myView.getMaxWidthInLineRange(i, i, true);
|
||||
final Ref<Boolean> approximateValue = new Ref<Boolean>(Boolean.FALSE);
|
||||
width = myView.getMaxWidthInLineRange(i, i, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
approximateValue.set(Boolean.TRUE);
|
||||
}
|
||||
});
|
||||
if (approximateValue.get()) width = -width;
|
||||
myLineWidths.set(i, width);
|
||||
}
|
||||
maxWidth = Math.max(maxWidth, Math.abs(width));
|
||||
@@ -230,11 +239,17 @@ class EditorSizeManager implements PrioritizedDocumentListener, Disposable, Fold
|
||||
try {
|
||||
int startVisualLine = myView.offsetToVisualLine(startOffset, false);
|
||||
int endVisualLine = myView.offsetToVisualLine(endOffset, true);
|
||||
boolean sizeInvalidated = false;
|
||||
for (int i = startVisualLine; i <= endVisualLine; i++) {
|
||||
myLineWidths.set(i, UNKNOWN_WIDTH);
|
||||
if (myLineWidths.get(i) < 0) {
|
||||
myLineWidths.set(i, UNKNOWN_WIDTH);
|
||||
sizeInvalidated = true;
|
||||
}
|
||||
}
|
||||
if (sizeInvalidated) {
|
||||
myWidthInPixels = -1;
|
||||
myEditor.getContentComponent().revalidate();
|
||||
}
|
||||
myWidthInPixels = -1;
|
||||
myEditor.getContentComponent().revalidate();
|
||||
}
|
||||
finally {
|
||||
myEditor.setPurePaintingMode(purePaintingMode);
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.font.FontRenderContext;
|
||||
@@ -238,17 +239,22 @@ public class EditorView implements TextDrawingCallback, Disposable {
|
||||
|
||||
public int getMaxWidthInRange(int startOffset, int endOffset) {
|
||||
assertIsDispatchThread();
|
||||
return getMaxWidthInLineRange(offsetToVisualLine(startOffset, false), offsetToVisualLine(endOffset, true), false);
|
||||
return getMaxWidthInLineRange(offsetToVisualLine(startOffset, false), offsetToVisualLine(endOffset, true), null);
|
||||
}
|
||||
|
||||
int getMaxWidthInLineRange(int startVisualLine, int endVisualLine, boolean quick) {
|
||||
|
||||
/**
|
||||
* If <code>quickEvaluationListener</code> is provided, quick approximate size evaluation becomes enabled, listener will be invoked
|
||||
* if approximation will in fact be used during width calculation.
|
||||
*/
|
||||
int getMaxWidthInLineRange(int startVisualLine, int endVisualLine, @Nullable Runnable quickEvaluationListener) {
|
||||
int maxWidth = 0;
|
||||
endVisualLine = Math.min(endVisualLine, myEditor.getVisibleLineCount() - 1);
|
||||
for (int i = startVisualLine; i <= endVisualLine; i++) {
|
||||
int startOffset = myMapper.visualLineToOffset(i);
|
||||
float x = 0;
|
||||
int maxOffset = 0;
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(this, startOffset, false, quick)) {
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(this, startOffset, false,
|
||||
quickEvaluationListener)) {
|
||||
x = fragment.getEndX();
|
||||
maxOffset = Math.max(maxOffset, fragment.getMaxOffset());
|
||||
}
|
||||
|
||||
@@ -240,13 +240,17 @@ class LineLayout {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* If <code>quickEvaluationListener</code> is provided, quick approximate iteration becomes enabled, listener will be invoked
|
||||
* if approximation will in fact be used during width calculation.
|
||||
*/
|
||||
Iterable<VisualFragment> getFragmentsInVisualOrder(@NotNull final EditorView view,
|
||||
final int lineStartOffset,
|
||||
final float startX,
|
||||
final int startVisualColumn,
|
||||
final int startOffset,
|
||||
int endOffset,
|
||||
boolean quick) {
|
||||
@Nullable Runnable quickEvaluationListener) {
|
||||
assert startOffset <= endOffset;
|
||||
final BidiRun[] runs;
|
||||
if (startOffset == endOffset) {
|
||||
@@ -257,7 +261,7 @@ class LineLayout {
|
||||
for (BidiRun run : myBidiRunsInLogicalOrder) {
|
||||
if (run.endOffset <= startOffset) continue;
|
||||
if (run.startOffset >= endOffset) break;
|
||||
runList.add(run.subRun(view, lineStartOffset, startOffset, endOffset, quick));
|
||||
runList.add(run.subRun(view, lineStartOffset, startOffset, endOffset, quickEvaluationListener));
|
||||
}
|
||||
runs = runList.toArray(new BidiRun[runList.size()]);
|
||||
reorderRunsVisually(runs);
|
||||
@@ -344,7 +348,8 @@ class LineLayout {
|
||||
return chunks;
|
||||
}
|
||||
|
||||
private BidiRun subRun(@NotNull EditorView view, int lineStartOffset, int targetStartOffset, int targetEndOffset, boolean quick) {
|
||||
private BidiRun subRun(@NotNull EditorView view, int lineStartOffset, int targetStartOffset, int targetEndOffset,
|
||||
@Nullable Runnable quickEvaluationListener) {
|
||||
assert targetStartOffset < endOffset;
|
||||
assert targetEndOffset > startOffset;
|
||||
int start = Math.max(startOffset, targetStartOffset);
|
||||
@@ -354,15 +359,15 @@ class LineLayout {
|
||||
for (Chunk chunk : getChunks()) {
|
||||
if (chunk.endOffset <= start) continue;
|
||||
if (chunk.startOffset >= end) break;
|
||||
subChunks.add(chunk.subChunk(view, this, lineStartOffset, start, end, quick));
|
||||
subChunks.add(chunk.subChunk(view, this, lineStartOffset, start, end, quickEvaluationListener));
|
||||
}
|
||||
subRun.chunks = subChunks.toArray(new Chunk[subChunks.size()]);
|
||||
return subRun;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Chunk {
|
||||
private final List<LineFragment> fragments = new ArrayList<LineFragment>(); // in logical order
|
||||
static class Chunk {
|
||||
final List<LineFragment> fragments = new ArrayList<LineFragment>(); // in logical order
|
||||
private int startOffset;
|
||||
private int endOffset;
|
||||
|
||||
@@ -372,6 +377,9 @@ class LineLayout {
|
||||
}
|
||||
|
||||
private void ensureLayout(@NotNull EditorView view, BidiRun run, int lineStartOffset) {
|
||||
if (isReal()) {
|
||||
view.getTextLayoutCache().onChunkAccess(this);
|
||||
}
|
||||
if (!fragments.isEmpty()) return;
|
||||
int start = lineStartOffset + startOffset;
|
||||
int end = lineStartOffset + endOffset;
|
||||
@@ -387,17 +395,15 @@ class LineLayout {
|
||||
assert !fragments.isEmpty();
|
||||
}
|
||||
|
||||
private Chunk subChunk(EditorView view, BidiRun run, int lineStartOffset, int targetStartOffset, int targetEndOffset, boolean quick) {
|
||||
private Chunk subChunk(EditorView view, BidiRun run, int lineStartOffset, int targetStartOffset, int targetEndOffset,
|
||||
@Nullable Runnable quickEvaluationListener) {
|
||||
assert targetStartOffset < endOffset;
|
||||
assert targetEndOffset > startOffset;
|
||||
int start = Math.max(startOffset, targetStartOffset);
|
||||
int end = Math.min(endOffset, targetEndOffset);
|
||||
if (quick && fragments.isEmpty()) {
|
||||
Chunk chunk = new Chunk(start, end);
|
||||
int startColumn = view.offsetToLogicalPosition(lineStartOffset + start).column;
|
||||
int endColumn = view.offsetToLogicalPosition(lineStartOffset + end).column;
|
||||
chunk.fragments.add(new ApproximationFragment(end - start, endColumn - startColumn, view.getMaxCharWidth()));
|
||||
return chunk;
|
||||
if (quickEvaluationListener != null && fragments.isEmpty()) {
|
||||
quickEvaluationListener.run();
|
||||
return new ApproximationChunk(view, lineStartOffset, start, end);
|
||||
}
|
||||
if (start == startOffset && end == this.endOffset) {
|
||||
return this;
|
||||
@@ -415,6 +421,28 @@ class LineLayout {
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
boolean isReal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void clearCache() {
|
||||
fragments.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ApproximationChunk extends Chunk {
|
||||
private ApproximationChunk(@NotNull EditorView view, int lineStartOffset, int start, int end) {
|
||||
super(start, end);
|
||||
int startColumn = view.offsetToLogicalPosition(lineStartOffset + start).column;
|
||||
int endColumn = view.offsetToLogicalPosition(lineStartOffset + end).column;
|
||||
fragments.add(new ApproximationFragment(end - start, endColumn - startColumn, view.getMaxCharWidth()));
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isReal() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class VisualOrderIterator implements Iterator<VisualFragment> {
|
||||
|
||||
+49
-4
@@ -20,11 +20,13 @@ import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.ex.PrioritizedDocumentListener;
|
||||
import com.intellij.openapi.editor.impl.EditorDocumentPriorities;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.util.ui.update.Activatable;
|
||||
import com.intellij.util.ui.update.UiNotifyConnector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Editor text layout storage. Layout is stored on a per-logical-line basis,
|
||||
@@ -33,17 +35,39 @@ import java.util.Collections;
|
||||
* @see LineLayout
|
||||
*/
|
||||
class TextLayoutCache implements PrioritizedDocumentListener, Disposable {
|
||||
private static final int MAX_CHUNKS_IN_ACTIVE_EDITOR = 1000;
|
||||
private static final int MAX_CHUNKS_IN_INACTIVE_EDITOR = 10;
|
||||
|
||||
private final EditorView myView;
|
||||
private final Document myDocument;
|
||||
private final LineLayout myBidiNotRequiredMarker;
|
||||
private ArrayList<LineLayout> myLines = new ArrayList<LineLayout>();
|
||||
private int myDocumentChangeOldEndLine;
|
||||
|
||||
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
|
||||
private LinkedHashMap<LineLayout.Chunk, Object> myLaidOutChunks =
|
||||
new LinkedHashMap<LineLayout.Chunk, Object>(MAX_CHUNKS_IN_ACTIVE_EDITOR, 0.75f, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<LineLayout.Chunk, Object> eldest) {
|
||||
if (size() > getChunkCacheSizeLimit()) {
|
||||
eldest.getKey().clearCache();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
TextLayoutCache(EditorView view) {
|
||||
myView = view;
|
||||
myDocument = view.getEditor().getDocument();
|
||||
myDocument.addDocumentListener(this, this);
|
||||
myBidiNotRequiredMarker = new LineLayout(view, "", Font.PLAIN);
|
||||
Disposer.register(this, new UiNotifyConnector(view.getEditor().getContentComponent(), new Activatable.Adapter() {
|
||||
@Override
|
||||
public void hideNotify() {
|
||||
trimChunkCache();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,12 +90,13 @@ class TextLayoutCache implements PrioritizedDocumentListener, Disposable {
|
||||
@Override
|
||||
public void dispose() {
|
||||
myLines = null;
|
||||
myLaidOutChunks = null;
|
||||
}
|
||||
|
||||
private int getAdjustedLineNumber(int offset) {
|
||||
return myDocument.getTextLength() == 0 ? -1 : myDocument.getLineNumber(offset);
|
||||
}
|
||||
|
||||
|
||||
void resetToDocumentSize(boolean documentChangedWithoutNotification) {
|
||||
checkDisposed();
|
||||
invalidateLines(0, myLines.size() - 1, myDocument.getLineCount() - 1, !documentChangedWithoutNotification);
|
||||
@@ -80,7 +105,7 @@ class TextLayoutCache implements PrioritizedDocumentListener, Disposable {
|
||||
void invalidateLines(int startLine, int endLine) {
|
||||
invalidateLines(startLine, endLine, endLine, true);
|
||||
}
|
||||
|
||||
|
||||
private void invalidateLines(int startLine, int oldEndLine, int newEndLine, boolean keepBidiNotRequiredState) {
|
||||
checkDisposed();
|
||||
int endLine = Math.min(oldEndLine, newEndLine);
|
||||
@@ -115,6 +140,26 @@ class TextLayoutCache implements PrioritizedDocumentListener, Disposable {
|
||||
return new LineLayout(myView, lineStart, lineEnd, skipBidiLayout);
|
||||
}
|
||||
|
||||
private int getChunkCacheSizeLimit() {
|
||||
return myView.getEditor().getContentComponent().isShowing() ? MAX_CHUNKS_IN_ACTIVE_EDITOR : MAX_CHUNKS_IN_INACTIVE_EDITOR;
|
||||
}
|
||||
|
||||
void onChunkAccess(LineLayout.Chunk chunk) {
|
||||
myLaidOutChunks.put(chunk, null);
|
||||
}
|
||||
|
||||
private void trimChunkCache() {
|
||||
int limit = getChunkCacheSizeLimit();
|
||||
if (myLaidOutChunks.size() > limit) {
|
||||
Iterator<LineLayout.Chunk> it = myLaidOutChunks.keySet().iterator();
|
||||
while (myLaidOutChunks.size() > limit) {
|
||||
LineLayout.Chunk chunk = it.next();
|
||||
chunk.clearCache();
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkDisposed() {
|
||||
if (myLines == null) throw new IllegalStateException("Editor is already disposed");
|
||||
}
|
||||
|
||||
+13
-6
@@ -22,6 +22,7 @@ import com.intellij.openapi.editor.ex.FoldingModelEx;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
import com.intellij.openapi.editor.impl.EditorImpl;
|
||||
import com.intellij.openapi.editor.impl.SoftWrapModelImpl;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Iterator;
|
||||
@@ -34,11 +35,16 @@ import java.util.NoSuchElementException;
|
||||
*/
|
||||
class VisualLineFragmentsIterator implements Iterator<VisualLineFragmentsIterator.Fragment> {
|
||||
|
||||
static Iterable<Fragment> create(final EditorView view, final int offset, final boolean beforeSoftWrap, final boolean quick) {
|
||||
/**
|
||||
* If <code>quickEvaluationListener</code> is provided, quick approximate iteration mode becomes enabled, listener will be invoked
|
||||
* if approximation will in fact be used during width calculation.
|
||||
*/
|
||||
static Iterable<Fragment> create(final EditorView view, final int offset, final boolean beforeSoftWrap,
|
||||
@Nullable final Runnable quickEvaluationListener) {
|
||||
return new Iterable<Fragment>() {
|
||||
@Override
|
||||
public Iterator<Fragment> iterator() {
|
||||
return new VisualLineFragmentsIterator(view, offset, beforeSoftWrap, quick);
|
||||
return new VisualLineFragmentsIterator(view, offset, beforeSoftWrap, quickEvaluationListener);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -48,7 +54,7 @@ class VisualLineFragmentsIterator implements Iterator<VisualLineFragmentsIterato
|
||||
private final FoldRegion[] myRegions;
|
||||
private final Fragment myFragment = new Fragment();
|
||||
private final int myVisualLineStartOffset;
|
||||
private final boolean myQuick;
|
||||
private final Runnable myQuickEvaluationListener;
|
||||
|
||||
private int mySegmentStartOffset;
|
||||
private int mySegmentEndOffset;
|
||||
@@ -62,8 +68,8 @@ class VisualLineFragmentsIterator implements Iterator<VisualLineFragmentsIterato
|
||||
private int myCurrentEndLogicalLine;
|
||||
private int myNextWrapOffset;
|
||||
|
||||
private VisualLineFragmentsIterator(EditorView view, int offset, boolean beforeSoftWrap, boolean quick) {
|
||||
myQuick = quick;
|
||||
private VisualLineFragmentsIterator(EditorView view, int offset, boolean beforeSoftWrap, @Nullable Runnable quickEvaluationListener) {
|
||||
myQuickEvaluationListener = quickEvaluationListener;
|
||||
myView = view;
|
||||
EditorImpl editor = view.getEditor();
|
||||
myDocument = editor.getDocument();
|
||||
@@ -112,7 +118,8 @@ class VisualLineFragmentsIterator implements Iterator<VisualLineFragmentsIterato
|
||||
int lineStartOffset = myDocument.getLineStartOffset(line);
|
||||
myFragmentIterator = myView.getTextLayoutCache().getLineLayout(line).
|
||||
getFragmentsInVisualOrder(myView, lineStartOffset, myCurrentX, myCurrentVisualColumn,
|
||||
mySegmentStartOffset - lineStartOffset, mySegmentEndOffset - lineStartOffset, myQuick).iterator();
|
||||
mySegmentStartOffset - lineStartOffset, mySegmentEndOffset - lineStartOffset,
|
||||
myQuickEvaluationListener).iterator();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user