blob: 1097f282444525de3528e385c7602831da340297 [file] [log] [blame]
/*
* Copyright 2000-2014 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.mapping;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.impl.SoftWrapModelImpl;
import org.jetbrains.annotations.NotNull;
/**
* Utility class that is assumed to be used for internal purposes only.
* <p/>
* Allows to hold complete information about particular position of document exposed via IJ editor and provides utility
* methods for working with it.
*
* @author Denis Zhdanov
* @since Sep 1, 2010 12:16:38 PM
*/
class EditorPosition implements Cloneable {
public int logicalLine;
public int logicalColumn;
public int visualLine;
public int visualColumn;
public int offset;
public int softWrapLinesBefore;
public int softWrapLinesCurrent;
public int softWrapColumnDiff;
public int foldedLines;
public int foldingColumnDiff;
public int x;
public char symbol;
public int symbolWidthInColumns;
public int symbolWidthInPixels;
private final Editor myEditor;
EditorPosition(@NotNull Editor editor) {
myEditor = editor;
}
EditorPosition(@NotNull LogicalPosition logical,
int offset,
@NotNull Editor editor)
{
this(logical, logical.toVisualPosition(), offset, editor);
}
EditorPosition(@NotNull LogicalPosition logical,
@NotNull VisualPosition visual,
int offset,
@NotNull Editor editor)
{
myEditor = editor;
logicalLine = logical.line;
logicalColumn = logical.column;
softWrapLinesBefore = logical.softWrapLinesBeforeCurrentLogicalLine;
softWrapLinesCurrent = logical.softWrapLinesOnCurrentLogicalLine;
softWrapColumnDiff = logical.softWrapColumnDiff;
foldedLines = logical.foldedLines;
foldingColumnDiff = logical.foldingColumnDiff;
visualLine = visual.line;
visualColumn = visual.column;
this.offset = offset;
}
@NotNull
public LogicalPosition buildLogicalPosition() {
return new LogicalPosition(
logicalLine, logicalColumn, softWrapLinesBefore, softWrapLinesCurrent, softWrapColumnDiff, foldedLines, foldingColumnDiff
);
}
@NotNull
public VisualPosition buildVisualPosition() {
return new VisualPosition(visualLine, visualColumn);
}
/**
* Asks current position to change its state assuming that it should point to the start of the next visual line.
*
* @param softWrapAware flag that indicates if state update should check if current visual line ends with soft wrap
*/
public void onNewLine(boolean softWrapAware) {
if (!softWrapAware || myEditor.getSoftWrapModel().getSoftWrap(offset) == null) {
onNewLine();
return;
}
softWrapLinesCurrent++;
softWrapColumnDiff = -logicalColumn - foldingColumnDiff;
visualLine++;
visualColumn = 0;
x = 0;
}
/**
* Similar as {@link #onNewLine(boolean)} with <code>'false'</code> argument.
*/
public void onNewLine() {
softWrapLinesBefore += softWrapLinesCurrent;
softWrapLinesCurrent = 0;
softWrapColumnDiff = 0;
foldingColumnDiff = 0;
visualLine++;
visualColumn = 0;
logicalLine++;
logicalColumn = 0;
x = 0;
offset++;
}
/**
* Updates state of the current processing position in order to point it to the end offset of the given fold region.
*
* @param foldRegion fold region which end offset should be pointed by the current position
* @param collapsedSymbolsWidthInColumns identifies collapsed text width in columns, i.e. width of the last collapsed logical line
* in columns, negative value, if it's unknown and needs to be calculated
*/
public void advance(@NotNull FoldRegion foldRegion, int collapsedSymbolsWidthInColumns) {
// We assume that fold region placeholder contains only 'simple' symbols, i.e. symbols that occupy single visual column.
String placeholder = foldRegion.getPlaceholderText();
visualColumn += placeholder.length();
offset = foldRegion.getEndOffset();
Document document = myEditor.getDocument();
int endOffsetLogicalLine = document.getLineNumber(foldRegion.getEndOffset());
if (logicalLine == endOffsetLogicalLine) {
// Single-line fold region.
if (collapsedSymbolsWidthInColumns < 0) {
collapsedSymbolsWidthInColumns = SoftWrapModelImpl.getEditorTextRepresentationHelper(myEditor)
.toVisualColumnSymbolsNumber(document.getCharsSequence(),
foldRegion.getStartOffset(),
foldRegion.getEndOffset(),
x);
}
logicalColumn += collapsedSymbolsWidthInColumns;
foldingColumnDiff += placeholder.length() - collapsedSymbolsWidthInColumns;
}
else {
// Multi-line fold region.
if (collapsedSymbolsWidthInColumns < 0) {
collapsedSymbolsWidthInColumns = SoftWrapModelImpl.getEditorTextRepresentationHelper(myEditor)
.toVisualColumnSymbolsNumber(document.getCharsSequence(),
foldRegion.getStartOffset(),
foldRegion.getEndOffset(),
0);
}
int linesDiff = endOffsetLogicalLine - logicalLine;
logicalLine += linesDiff;
foldedLines += linesDiff;
logicalColumn = collapsedSymbolsWidthInColumns;
foldingColumnDiff = visualColumn - logicalColumn - softWrapColumnDiff;
}
}
public void from(@NotNull EditorPosition position) {
logicalLine = position.logicalLine;
logicalColumn = position.logicalColumn;
visualLine = position.visualLine;
visualColumn = position.visualColumn;
offset = position.offset;
softWrapLinesBefore = position.softWrapLinesBefore;
softWrapLinesCurrent = position.softWrapLinesCurrent;
softWrapColumnDiff = position.softWrapColumnDiff;
foldedLines = position.foldedLines;
foldingColumnDiff = position.foldingColumnDiff;
x = position.x;
symbol = position.symbol;
symbolWidthInColumns = position.symbolWidthInColumns;
symbolWidthInPixels = position.symbolWidthInPixels;
}
@Override
protected EditorPosition clone() {
EditorPosition result = new EditorPosition(myEditor);
result.logicalLine = logicalLine;
result.logicalColumn = logicalColumn;
result.visualLine = visualLine;
result.visualColumn = visualColumn;
result.offset = offset;
result.softWrapLinesBefore = softWrapLinesBefore;
result.softWrapLinesCurrent = softWrapLinesCurrent;
result.softWrapColumnDiff = softWrapColumnDiff;
result.foldedLines = foldedLines;
result.foldingColumnDiff = foldingColumnDiff;
result.x = x;
result.symbol = symbol;
result.symbolWidthInColumns = symbolWidthInColumns;
result.symbolWidthInPixels = symbolWidthInPixels;
return result;
}
@Override
public String toString() {
return String.format(
"visual position: (%d; %d); logical position: (%d; %d); offset: %d; soft wraps: before=%d, current=%d, column diff=%d; "
+ "fold regions: lines=%d, column diff=%d", visualLine, visualColumn, logicalLine, logicalColumn, offset, softWrapLinesBefore,
softWrapLinesCurrent, softWrapColumnDiff, foldedLines, foldingColumnDiff);
}
}