blob: 30a7a0e5ad205a8d9622021641a29350f400f61a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2012 Avaloq Evolution AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Tom Eicher (Avaloq Evolution AG) - initial API and implementation
*******************************************************************************/
package org.eclipse.jface.internal.text;
import java.util.Arrays;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.GC;
import org.eclipse.core.runtime.Assert;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BlockTextSelection;
import org.eclipse.jface.text.IBlockTextSelection;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.IRewriteTarget;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.TextUtilities;
/**
* Processes {@link ITextSelection}s.
*
* @since 3.5
*/
public final class SelectionProcessor {
private static class Implementation {
/**
* Returns a text edit describing the text modification that would be executed if the given
* selection was replaced by <code>replacement</code>.
*
* @param selection the selection to replace
* @param replacement the replacement text
* @return a text edit describing the operation needed to replace <code>selection</code>
* @throws BadLocationException if computing the edit failed
*/
TextEdit replace(ISelection selection, String replacement) throws BadLocationException {
return new MultiTextEdit();
}
/**
* Returns the text covered by <code>selection</code>
*
* @param selection the selection
* @return the text covered by <code>selection</code>
* @throws BadLocationException if computing the edit failed
*/
String getText(ISelection selection) throws BadLocationException {
return ""; //$NON-NLS-1$
}
/**
* Returns <code>true</code> if the text covered by <code>selection</code> does not contain any
* characters. Note the difference to {@link ITextSelection#isEmpty()}, which returns
* <code>true</code> only for invalid selections.
*
* @param selection the selection
* @return <code>true</code> if <code>selection</code> does not contain any text,
* <code>false</code> otherwise
* @throws BadLocationException if accessing the document failed
*/
boolean isEmpty(ISelection selection) throws BadLocationException {
return selection.isEmpty();
}
/**
* Returns <code>true</code> if <code>selection</code> covers text on two or more lines,
* <code>false</code> otherwise.
*
* @param selection the selection
* @return <code>true</code> if <code>selection</code> covers text on two or more lines,
* <code>false</code> otherwise
* @throws BadLocationException if selection is not a valid selection on the target document
*/
boolean isMultiline(ISelection selection) throws BadLocationException {
if (selection == null)
throw new NullPointerException();
return false;
}
TextEdit delete(ISelection selection) throws BadLocationException {
return replace(selection, ""); //$NON-NLS-1$
}
TextEdit backspace(ISelection selection) throws BadLocationException {
return replace(selection, ""); //$NON-NLS-1$
}
/**
* Returns a selection similar to <code>selection</code> but {@linkplain #isEmpty(ISelection)
* empty}. Typically, the selection is reduced to its left-most offset.
*
* @param selection the selection
* @param beginning <code>true</code> to collapse the selection to its smallest position
* (i.e. its left-most offset), <code>false</code> to collapse it to its greatest
* position (e.g its right-most offset)
* @return an empty variant of <code>selection</code>
* @throws BadLocationException if accessing the document failed
*/
ISelection makeEmpty(ISelection selection, boolean beginning) throws BadLocationException {
return selection;
}
/**
* Returns the text regions covered by the given selection.
*
* @param selection the selection
* @return the text regions corresponding to <code>selection</code>
* @throws BadLocationException if accessing the document failed
*/
IRegion[] getRanges(ISelection selection) throws BadLocationException {
return new IRegion[0];
}
/**
* Returns the number of lines touched by <code>selection</code>.
*
* @param selection the selection
* @return the number of lines touched by <code>selection</code>
* @throws BadLocationException if accessing the document failed
*/
int getCoveredLines(ISelection selection) throws BadLocationException {
return 0;
}
/**
* Returns the selection after replacing <code>selection</code> by <code>replacement</code>.
*
* @param selection the selection to be replaced
* @param replacement the replacement text
* @return the selection that the user expects after the specified replacement operation
* @throws BadLocationException if accessing the document failed
*/
ISelection makeReplaceSelection(ISelection selection, String replacement) throws BadLocationException {
return makeEmpty(selection, false);
}
}
private final Implementation NULL_IMPLEMENTATION= new Implementation();
private final Implementation RANGE_IMPLEMENTATION= new Implementation() {
TextEdit replace(ISelection selection, String replacement) {
ITextSelection ts= (ITextSelection)selection;
return new ReplaceEdit(ts.getOffset(), ts.getLength(), replacement);
}
String getText(ISelection selection) {
ITextSelection ts= (ITextSelection)selection;
return ts.getText();
}
boolean isEmpty(ISelection selection) {
ITextSelection ts= (ITextSelection)selection;
return ts.getLength() <= 0;
}
boolean isMultiline(ISelection selection) throws BadLocationException {
ITextSelection ts= (ITextSelection)selection;
return fDocument.getLineOfOffset(ts.getOffset()) < fDocument.getLineOfOffset(ts.getOffset() + ts.getLength());
}
TextEdit delete(ISelection selection) {
ITextSelection ts= (ITextSelection)selection;
if (isEmpty(selection))
return new DeleteEdit(ts.getOffset(), 1);
return new DeleteEdit(ts.getOffset(), ts.getLength());
}
TextEdit backspace(ISelection selection) throws BadLocationException {
ITextSelection ts= (ITextSelection)selection;
if (isEmpty(selection))
return new DeleteEdit(ts.getOffset() - 1, 1);
return new DeleteEdit(ts.getOffset(), ts.getLength());
}
ISelection makeEmpty(ISelection selection, boolean beginning) {
ITextSelection ts= (ITextSelection)selection;
return beginning ?
new TextSelection(fDocument, ts.getOffset(), 0)
: new TextSelection(fDocument, ts.getOffset() + ts.getLength(), 0);
}
IRegion[] getRanges(ISelection selection) {
ITextSelection ts= (ITextSelection)selection;
return new IRegion[] { new Region(ts.getOffset(), ts.getLength()) };
}
int getCoveredLines(ISelection selection) throws BadLocationException {
ITextSelection ts= (ITextSelection)selection;
return ts.getEndLine() - ts.getStartLine() + 1;
}
ISelection makeReplaceSelection(ISelection selection, String replacement) {
ITextSelection ts= (ITextSelection)selection;
return new TextSelection(fDocument, ts.getOffset() + replacement.length(), 0);
}
};
private final Implementation COLUMN_IMPLEMENTATION= new Implementation() {
private TextEdit replace(ISelection selection, String replacement, boolean delete) throws BadLocationException {
try {
MultiTextEdit root;
IBlockTextSelection cts= (IBlockTextSelection)selection;
int startLine= cts.getStartLine();
int endLine= cts.getEndLine();
int startColumn= cts.getStartColumn();
int endColumn= cts.getEndColumn();
int visualStartColumn= computeVisualColumn(startLine, startColumn);
int visualEndColumn= computeVisualColumn(endLine, endColumn);
root= new MultiTextEdit();
String[] delimiters= fDocument.getLegalLineDelimiters();
int lastDelim= 0;
for (int line= startLine; line <= endLine; line++) {
String string;
if (lastDelim == -1) {
string= ""; //$NON-NLS-1$
} else {
int[] index= TextUtilities.indexOf(delimiters, replacement, lastDelim);
if (index[0] == -1) {
string= replacement.substring(lastDelim);
lastDelim= -1;
} else {
string= replacement.substring(lastDelim, index[0]);
lastDelim= index[0] + delimiters[index[1]].length();
}
}
TextEdit replace= createReplaceEdit(line, visualStartColumn, visualEndColumn, string, delete);
root.addChild(replace);
}
while (lastDelim != -1) {
// more stuff to insert
String string;
int[] index= TextUtilities.indexOf(delimiters, replacement, lastDelim);
if (index[0] == -1) {
string= replacement.substring(lastDelim);
lastDelim= -1;
} else {
string= replacement.substring(lastDelim, index[0]);
lastDelim= index[0] + delimiters[index[1]].length();
}
endLine++;
TextEdit edit;
if (endLine < fDocument.getNumberOfLines()) {
edit= createReplaceEdit(endLine, visualStartColumn, visualEndColumn, string, delete);
} else {
// insertion reaches beyond the last line
int insertLocation= root.getExclusiveEnd();
int spaces= visualStartColumn;
char[] array= new char[spaces];
Arrays.fill(array, ' ');
string= TextUtilities.getDefaultLineDelimiter(fDocument) + String.valueOf(array) + string;
edit= new InsertEdit(insertLocation, string);
insertLocation+= string.length();
}
root.addChild(edit);
}
return root;
} catch (MalformedTreeException x) {
Assert.isTrue(false);
return null;
}
}
TextEdit replace(ISelection selection, String replacement) throws BadLocationException {
return replace(selection, replacement, false);
}
String getText(ISelection selection) throws BadLocationException {
IBlockTextSelection cts= (IBlockTextSelection)selection;
StringBuffer buf= new StringBuffer(cts.getLength());
int startLine= cts.getStartLine();
int endLine= cts.getEndLine();
int startColumn= cts.getStartColumn();
int endColumn= cts.getEndColumn();
int visualStartColumn= computeVisualColumn(startLine, startColumn);
int visualEndColumn= computeVisualColumn(endLine, endColumn);
for (int line= startLine; line <= endLine; line++) {
appendColumnRange(buf, line, visualStartColumn, visualEndColumn);
if (line != endLine)
buf.append(fDocument.getLineDelimiter(line));
}
return buf.toString();
}
boolean isEmpty(ISelection selection) throws BadLocationException {
IBlockTextSelection cts= (IBlockTextSelection)selection;
int startLine= cts.getStartLine();
int endLine= cts.getEndLine();
int startColumn= cts.getStartColumn();
int endColumn= cts.getEndColumn();
int visualStartColumn= computeVisualColumn(startLine, startColumn);
int visualEndColumn= computeVisualColumn(endLine, endColumn);
return visualEndColumn == visualStartColumn;
}
boolean isMultiline(ISelection selection) {
ITextSelection ts= (ITextSelection)selection;
return ts.getEndLine() > ts.getStartLine();
}
TextEdit delete(ISelection selection) throws BadLocationException {
if (isEmpty(selection)) {
IBlockTextSelection cts= (IBlockTextSelection)selection;
selection= new BlockTextSelection(fDocument, cts.getStartLine(), cts.getStartColumn(), cts.getEndLine(), cts.getEndColumn() + 1, fTabWidth);
}
return replace(selection, "", true); //$NON-NLS-1$
}
TextEdit backspace(ISelection selection) throws BadLocationException {
IBlockTextSelection cts= (IBlockTextSelection)selection;
if (isEmpty(selection) && cts.getStartColumn() > 0) {
selection= new BlockTextSelection(fDocument, cts.getStartLine(), cts.getStartColumn() - 1, cts.getEndLine(), cts.getEndColumn(), fTabWidth);
}
return replace(selection, ""); //$NON-NLS-1$
}
ISelection makeEmpty(ISelection selection, boolean beginning) throws BadLocationException {
IBlockTextSelection cts= (IBlockTextSelection)selection;
int startLine, startColumn, endLine, endColumn;
if (beginning) {
startLine= cts.getStartLine();
startColumn= cts.getStartColumn();
endLine= cts.getEndLine();
endColumn= computeCharacterColumn(endLine, computeVisualColumn(startLine, startColumn));
} else {
endLine= cts.getEndLine();
endColumn= cts.getEndColumn();
startLine= cts.getStartLine();
startColumn= computeCharacterColumn(startLine, computeVisualColumn(endLine, endColumn));
}
return new BlockTextSelection(fDocument, startLine, startColumn, endLine, endColumn, fTabWidth);
}
ISelection makeReplaceSelection(ISelection selection, String replacement) throws BadLocationException {
IBlockTextSelection bts= (IBlockTextSelection)selection;
String[] delimiters= fDocument.getLegalLineDelimiters();
int[] index= TextUtilities.indexOf(delimiters, replacement, 0);
int length;
if (index[0] == -1)
length= replacement.length();
else
length= index[0];
int startLine= bts.getStartLine();
int column= bts.getStartColumn() + length;
int endLine= bts.getEndLine();
int endColumn= computeCharacterColumn(endLine, computeVisualColumn(startLine, column));
return new BlockTextSelection(fDocument, startLine, column, endLine, endColumn, fTabWidth);
}
IRegion[] getRanges(ISelection selection) throws BadLocationException {
IBlockTextSelection cts= (IBlockTextSelection)selection;
final int startLine= cts.getStartLine();
final int endLine= cts.getEndLine();
int visualStartColumn= computeVisualColumn(startLine, cts.getStartColumn());
int visualEndColumn= computeVisualColumn(endLine, cts.getEndColumn());
IRegion[] ranges= new IRegion[endLine - startLine + 1];
for (int line= startLine; line <= endLine; line++) {
int startColumn= computeCharacterColumn(line, visualStartColumn);
int endColumn= computeCharacterColumn(line, visualEndColumn);
IRegion lineInfo= fDocument.getLineInformation(line);
int lineEnd= lineInfo.getLength();
startColumn= Math.min(startColumn, lineEnd);
endColumn= Math.min(endColumn, lineEnd);
ranges[line - startLine]= new Region(lineInfo.getOffset() + startColumn, endColumn - startColumn);
}
return ranges;
}
int getCoveredLines(ISelection selection) throws BadLocationException {
ITextSelection ts= (ITextSelection)selection;
return ts.getEndLine() - ts.getStartLine() + 1;
}
private TextEdit createReplaceEdit(int line, int visualStartColumn, int visualEndColumn, String replacement, boolean delete) throws BadLocationException {
IRegion info= fDocument.getLineInformation(line);
int lineLength= info.getLength();
String content= fDocument.get(info.getOffset(), lineLength);
int startColumn= -1;
int endColumn= -1;
int visual= 0;
for (int offset= 0; offset < lineLength; offset++) {
if (startColumn == -1) {
if (visual == visualStartColumn)
if (!delete && isWider(content.charAt(offset), visual) && replacement.length() == 0)
startColumn= offset - 1;
else
startColumn= offset;
else if (visual > visualStartColumn) {
if (isWider(content.charAt(offset - 1), visual))
startColumn= offset - 1;
else
startColumn= offset;
}
}
if (startColumn != -1) {
if (visual == visualEndColumn) {
endColumn= offset;
break;
} else if (visual > visualEndColumn) {
if (!delete && isWider(content.charAt(offset - 1), visual))
endColumn= offset - 1;
else
endColumn= offset;
break;
}
}
visual+= visualSizeIncrement(content.charAt(offset), visual);
}
if (startColumn == -1) {
boolean materializeVirtualSpace= replacement.length() != 0;
if (materializeVirtualSpace) {
int spaces= Math.max(0, visualStartColumn - visual);
char[] array= new char[spaces];
Arrays.fill(array, ' ');
return new InsertEdit(info.getOffset() + lineLength, String.valueOf(array) + replacement);
}
return new MultiTextEdit();
}
if (endColumn == -1)
endColumn= lineLength;
if (replacement.length() == 0)
return new DeleteEdit(info.getOffset() + startColumn, endColumn - startColumn);
return new ReplaceEdit(info.getOffset() + startColumn, endColumn - startColumn, replacement);
}
private void appendColumnRange(StringBuffer buf, int line, int visualStartColumn, int visualEndColumn) throws BadLocationException {
IRegion info= fDocument.getLineInformation(line);
int lineLength= info.getLength();
String content= fDocument.get(info.getOffset(), lineLength);
int startColumn= -1;
int endColumn= -1;
int visual= 0;
for (int offset= 0; offset < lineLength; offset++) {
if (startColumn == -1 && visual >= visualStartColumn)
startColumn= offset;
if (visual >= visualEndColumn) {
endColumn= offset;
break;
}
visual+= visualSizeIncrement(content.charAt(offset), visual);
}
if (startColumn != -1)
buf.append(content.substring(startColumn, endColumn == -1 ? lineLength : endColumn));
if (endColumn == -1) {
int spaces= Math.max(0, visualEndColumn - Math.max(visual, visualStartColumn));
for (int i= 0; i < spaces; i++)
buf.append(' ');
}
}
private int computeVisualColumn(final int line, final int column) throws BadLocationException {
IRegion info= fDocument.getLineInformation(line);
int lineLength= info.getLength();
int to= Math.min(lineLength, column);
String content= fDocument.get(info.getOffset(), lineLength);
int visual= 0;
for (int offset= 0; offset < to; offset++)
visual+= visualSizeIncrement(content.charAt(offset), visual);
if (column > lineLength)
visual+= column - lineLength; // virtual spaces
return visual;
}
private int computeCharacterColumn(int line, int visualColumn) throws BadLocationException {
IRegion info= fDocument.getLineInformation(line);
int lineLength= info.getLength();
String content= fDocument.get(info.getOffset(), lineLength);
int visual= 0;
for (int offset= 0; offset < lineLength; offset++) {
if (visual >= visualColumn)
return offset;
visual+= visualSizeIncrement(content.charAt(offset), visual);
}
return lineLength + Math.max(0, visualColumn - visual);
}
private boolean isWider(char character, int visual) {
return visualSizeIncrement(character, visual) > 1;
}
/**
* Returns the increment in visual length represented by <code>character</code> given the
* current visual length. The visual length is <code>1</code> unless <code>character</code>
* is a tabulator (<code>\t</code>).
*
* @param character the character the length of which to compute
* @param visual the current visual length
* @return the increment in visual length represented by <code>character</code>, which is in
* <code>[0,fTabWidth]</code>
*/
private int visualSizeIncrement(char character, int visual) {
if (character > 255 && fStyledText != null) {
GC gc= null;
try {
gc= new GC(fStyledText);
int charWidth= gc.stringExtent(new String(Character.toString(character))).x;
int singleCharWidth= gc.stringExtent(" ").x; //$NON-NLS-1$
return (int)Math.ceil(charWidth / singleCharWidth);
} finally {
if (gc != null)
gc.dispose();
}
}
if (character != '\t')
return 1;
if (fTabWidth <= 0)
return 0;
return fTabWidth - visual % fTabWidth;
}
};
private final IDocument fDocument;
private final int fTabWidth;
private IRewriteTarget fRewriteTarget;
private ISelectionProvider fSelectionProvider;
private StyledText fStyledText;
/**
* Creates a new processor on the given viewer.
*
* @param viewer the viewer
*/
public SelectionProcessor(ITextViewer viewer) {
this(viewer.getDocument(), viewer.getTextWidget().getTabs());
if (viewer instanceof ITextViewerExtension) {
ITextViewerExtension ext= (ITextViewerExtension)viewer;
fRewriteTarget= ext.getRewriteTarget();
}
fSelectionProvider= viewer.getSelectionProvider();
fStyledText= viewer.getTextWidget();
}
/**
* Creates a new processor on the given document and using the given tab width.
*
* @param document the document
* @param tabWidth the tabulator width in space equivalents, must be <code>&gt;=0</code>
*/
public SelectionProcessor(IDocument document, int tabWidth) {
Assert.isNotNull(document);
Assert.isTrue(tabWidth >= 0);
fDocument= document;
fTabWidth= tabWidth;
}
/**
* Returns a text edit describing the text modification that would be executed if the delete key
* was pressed on the given selection.
*
* @param selection the selection to delete
* @return a text edit describing the operation needed to delete <code>selection</code>
* @throws BadLocationException if computing the edit failed
*/
public TextEdit delete(ISelection selection) throws BadLocationException {
return getImplementation(selection).delete(selection);
}
/**
* Returns a text edit describing the text modification that would be executed if the backspace
* key was pressed on the given selection.
*
* @param selection the selection to delete
* @return a text edit describing the operation needed to delete <code>selection</code>
* @throws BadLocationException if computing the edit failed
*/
public TextEdit backspace(ISelection selection) throws BadLocationException {
return getImplementation(selection).backspace(selection);
}
/**
* Returns a text edit describing the text modification that would be executed if the given
* selection was replaced by <code>replacement</code>.
*
* @param selection the selection to replace
* @param replacement the replacement text
* @return a text edit describing the operation needed to replace <code>selection</code>
* @throws BadLocationException if computing the edit failed
*/
public TextEdit replace(ISelection selection, String replacement) throws BadLocationException {
return getImplementation(selection).replace(selection, replacement);
}
/**
* Returns the text covered by <code>selection</code>
*
* @param selection the selection
* @return the text covered by <code>selection</code>
* @throws BadLocationException if computing the edit failed
*/
public String getText(ISelection selection) throws BadLocationException {
return getImplementation(selection).getText(selection);
}
/**
* Returns <code>true</code> if the text covered by <code>selection</code> does not contain any
* characters. Note the difference to {@link ITextSelection#isEmpty()}, which returns
* <code>true</code> only for invalid selections.
*
* @param selection the selection
* @return <code>true</code> if <code>selection</code> does not contain any text,
* <code>false</code> otherwise
* @throws BadLocationException if accessing the document failed
*/
public boolean isEmpty(ISelection selection) throws BadLocationException {
return getImplementation(selection).isEmpty(selection);
}
/**
* Returns <code>true</code> if <code>selection</code> extends to two or more lines,
* <code>false</code> otherwise.
*
* @param selection the selection
* @return <code>true</code> if <code>selection</code> extends to two or more lines,
* <code>false</code> otherwise
* @throws BadLocationException if <code>selection</code> is not valid regarding the target
* document
*/
public boolean isMultiline(ISelection selection) throws BadLocationException {
return getImplementation(selection).isMultiline(selection);
}
/**
* Returns a selection similar to <code>selection</code> but {@linkplain #isEmpty(ISelection)
* empty}. Typically, the selection is reduced to its extreme offsets.
*
* @param selection the selection
* @param beginning <code>true</code> to collapse the selection to its smallest position (i.e.
* its left-most offset), <code>false</code> to collapse it to its greatest position
* (e.g its right-most offset)
* @return an empty variant of <code>selection</code>
* @throws BadLocationException if accessing the document failed
*/
public ISelection makeEmpty(ISelection selection, boolean beginning) throws BadLocationException {
return getImplementation(selection).makeEmpty(selection, beginning);
}
private ISelection makeReplaceSelection(ISelection selection, String replacement) throws BadLocationException {
return getImplementation(selection).makeReplaceSelection(selection, replacement);
}
/**
* Convenience method that applies the edit returned from {@link #delete(ISelection)} to the
* underlying document.
*
* @param selection the selection to delete
* @throws BadLocationException if accessing the document failed
*/
public void doDelete(ISelection selection) throws BadLocationException {
TextEdit edit= delete(selection);
boolean complex= edit.hasChildren();
if (complex && fRewriteTarget != null)
fRewriteTarget.beginCompoundChange();
try {
edit.apply(fDocument, TextEdit.UPDATE_REGIONS);
if (fSelectionProvider != null) {
ISelection empty= makeEmpty(selection, true);
fSelectionProvider.setSelection(empty);
}
} finally {
if (complex && fRewriteTarget != null)
fRewriteTarget.endCompoundChange();
}
}
/**
* Convenience method that applies the edit returned from {@link #replace(ISelection, String)}
* to the underlying document and adapts the selection accordingly.
*
* @param selection the selection to replace
* @param replacement the replacement text
* @throws BadLocationException if accessing the document failed
*/
public void doReplace(ISelection selection, String replacement) throws BadLocationException {
TextEdit edit= replace(selection, replacement);
boolean complex= edit.hasChildren();
if (complex && fRewriteTarget != null)
fRewriteTarget.beginCompoundChange();
try {
edit.apply(fDocument, TextEdit.UPDATE_REGIONS);
if (fSelectionProvider != null) {
ISelection empty= makeReplaceSelection(selection, replacement);
fSelectionProvider.setSelection(empty);
}
} finally {
if (complex && fRewriteTarget != null)
fRewriteTarget.endCompoundChange();
}
}
/**
* Returns the text regions covered by the given selection.
*
* @param selection the selection
* @return the text regions corresponding to <code>selection</code>
* @throws BadLocationException if accessing the document failed
*/
public IRegion[] getRanges(ISelection selection) throws BadLocationException {
return getImplementation(selection).getRanges(selection);
}
/**
* Returns the number of lines touched by <code>selection</code>. Note that for linear
* selections, this is the number of contained delimiters plus 1.
*
* @param selection the selection
* @return the number of lines touched by <code>selection</code>
* @throws BadLocationException if accessing the document failed
*/
public int getCoveredLines(ISelection selection) throws BadLocationException {
return getImplementation(selection).getCoveredLines(selection);
}
/**
* Returns the implementation.
*
* @param selection the selection
* @return the corresponding processor implementation
*/
private Implementation getImplementation(ISelection selection) {
if (selection instanceof IBlockTextSelection)
return COLUMN_IMPLEMENTATION;
else if (selection instanceof ITextSelection)
return RANGE_IMPLEMENTATION;
else
return NULL_IMPLEMENTATION;
}
}