blob: d75a296aaed5d186b5c48a63f917dcb6930956ff [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 Avaloq Evolution AG and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Tom Eicher (Avaloq Evolution AG) - initial API and implementation
*******************************************************************************/
package org.eclipse.jface.text;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.internal.text.SelectionProcessor;
/**
* Standard implementation of {@link org.eclipse.jface.text.IBlockTextSelection}.
*
* @since 3.5
*/
public class BlockTextSelection extends TextSelection implements IBlockTextSelection {
/** The start line. */
private final int fStartLine;
/** The start column. */
private final int fStartColumn;
/** The end line. */
private final int fEndLine;
/** The end column. */
private final int fEndColumn;
/** The tabulator width used to compute visual columns from character offsets. */
private final int fTabWidth;
/**
* Creates a column selection for the given lines and columns.
*
* @param document the document that this selection refers to
* @param startLine the start line
* @param startColumn the possibly virtual start column, measured in characters from the start
* of <code>startLine</code>
* @param endLine the inclusive end line
* @param endColumn the exclusive and possibly virtual end column, measured in characters from
* the start of <code>endLine</code>
* @param tabWidth the tabulator width used to compute the visual offsets from character offsets
*/
public BlockTextSelection(IDocument document, int startLine, int startColumn, int endLine, int endColumn, int tabWidth) {
super(document, computeOffset(document, startLine, startColumn), computeOffset(document, endLine, endColumn) - computeOffset(document, startLine, startColumn));
Assert.isLegal(startLine >= 0);
Assert.isLegal(startColumn >= 0);
Assert.isLegal(endLine >= startLine);
Assert.isLegal(endColumn >= 0);
Assert.isLegal(tabWidth >= 0);
fStartLine= startLine;
fStartColumn= startColumn;
fEndLine= endLine;
fEndColumn= endColumn;
fTabWidth= tabWidth > 0 ? tabWidth : 8; // seems to be the default when StyledText.getTabs returns 0
}
/**
* Returns the document offset for a given tuple of line and column count. If the column count
* points beyond the end of the line, the end of the line is returned (virtual location). If the
* line points beyond the number of lines, the end of the document is returned; if the line is
* &lt; zero, 0 is returned.
*
* @param document the document to get line information from
* @param line the line in the document, may be greater than the line count
* @param column the offset in the given line, may be greater than the line length
* @return the document offset corresponding to the line and column counts
*/
private static int computeOffset(IDocument document, int line, int column) {
try {
IRegion lineInfo= document.getLineInformation(line);
int offsetInLine= Math.min(column, lineInfo.getLength());
return lineInfo.getOffset() + offsetInLine;
} catch (BadLocationException x) {
if (line < 0)
return 0;
return document.getLength();
}
}
@Override
public int getStartLine() {
return fStartLine;
}
@Override
public int getStartColumn() {
return fStartColumn;
}
@Override
public int getEndLine() {
return fEndLine;
}
@Override
public int getEndColumn() {
return fEndColumn;
}
@Override
public String getText() {
IDocument document= getDocument();
if (document != null) {
try {
return new SelectionProcessor(document, fTabWidth).getText(this);
} catch (BadLocationException x) {
// ignore and default to super implementation
}
}
return super.getText();
}
@Override
public int hashCode() {
final int prime= 31;
int result= super.hashCode();
result= prime * result + fEndColumn;
result= prime * result + fEndLine;
result= prime * result + fStartColumn;
result= prime * result + fStartLine;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
final BlockTextSelection other= (BlockTextSelection) obj;
if (fEndColumn != other.fEndColumn)
return false;
if (fEndLine != other.fEndLine)
return false;
if (fStartColumn != other.fStartColumn)
return false;
if (fStartLine != other.fStartLine)
return false;
return true;
}
@Override
public IRegion[] getRegions() {
IDocument document= getDocument();
if (document != null) {
try {
return new SelectionProcessor(document, fTabWidth).getRanges(this);
} catch (BadLocationException x) {
// default to single region behavior
}
}
return new IRegion[] {new Region(getOffset(), getLength())};
}
/**
* @since 3.16
*/
@Override
public String toString() {
StringBuilder sb= new StringBuilder();
sb.append("BlockTextSelection [offset: ").append(getOffset()); //$NON-NLS-1$
sb.append(", startLine: ").append(fStartLine); //$NON-NLS-1$
if (fEndLine != fStartLine) {
sb.append(", endLine: ").append(fEndLine); //$NON-NLS-1$
}
sb.append(", startColumn: ").append(fStartColumn); //$NON-NLS-1$
if (fEndColumn != fStartColumn) {
sb.append(", endColumn").append(fEndColumn); //$NON-NLS-1$
}
if (getLength() != 0) {
sb.append(", text: ").append(getText()); //$NON-NLS-1$
}
if (getDocument() != null) {
sb.append(", document: ").append(getDocument()); //$NON-NLS-1$
}
sb.append("]"); //$NON-NLS-1$
return sb.toString();
}
}