blob: be1ea743b21341083937c7d8a1894fcf1365bbae [file] [log] [blame]
package org.eclipse.ui.examples.javaeditor.java;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextDoubleClickStrategy;
import org.eclipse.jface.text.ITextViewer;
/**
* Double click strategy aware of Java identifier syntax rules.
*/
public class JavaDoubleClickSelector implements ITextDoubleClickStrategy {
protected ITextViewer fText;
protected int fPos;
protected int fStartPos;
protected int fEndPos;
protected static char[] fgBrackets= { '{', '}', '(', ')', '[', ']', '"', '"' };
/*
* Create a JavaDoubleClickSelector.
*/
public JavaDoubleClickSelector() {
super();
}
/* (non-Javadoc)
* Method declared on ITextDoubleClickStrategy
*/
public void doubleClicked(ITextViewer text) {
fPos= text.getSelectedRange().x;
if (fPos < 0)
return;
fText= text;
if (!selectBracketBlock())
selectWord();
}
/**
* Match the brackets at the current selection. Return true if successful,
* false otherwise.
*/
protected boolean matchBracketsAt() {
char prevChar, nextChar;
int i;
int bracketIndex1= fgBrackets.length;
int bracketIndex2= fgBrackets.length;
fStartPos= -1;
fEndPos= -1;
// get the chars preceding and following the start position
try {
IDocument doc= fText.getDocument();
prevChar= doc.getChar(fPos - 1);
nextChar= doc.getChar(fPos);
// is the char either an open or close bracket?
for (i= 0; i < fgBrackets.length; i= i + 2) {
if (prevChar == fgBrackets[i]) {
fStartPos= fPos - 1;
bracketIndex1= i;
}
}
for (i= 1; i < fgBrackets.length; i= i + 2) {
if (nextChar == fgBrackets[i]) {
fEndPos= fPos;
bracketIndex2= i;
}
}
if (fStartPos > -1 && bracketIndex1 < bracketIndex2) {
fEndPos= searchForClosingBracket(fStartPos, prevChar, fgBrackets[bracketIndex1 + 1], doc);
if (fEndPos > -1)
return true;
else
fStartPos= -1;
} else if (fEndPos > -1) {
fStartPos= searchForOpenBracket(fEndPos, fgBrackets[bracketIndex2 - 1], nextChar, doc);
if (fStartPos > -1)
return true;
else
fEndPos= -1;
}
} catch (BadLocationException x) {
}
return false;
}
/**
* Select the word at the current selection. Return true if successful,
* false otherwise.
*/
protected boolean matchWord() {
IDocument doc= fText.getDocument();
try {
int pos= fPos;
char c;
while (pos >= 0) {
c= doc.getChar(pos);
if (!Character.isJavaIdentifierPart(c))
break;
--pos;
}
fStartPos= pos;
pos= fPos;
int length= doc.getLength();
while (pos < length) {
c= doc.getChar(pos);
if (!Character.isJavaIdentifierPart(c))
break;
++pos;
}
fEndPos= pos;
return true;
} catch (BadLocationException x) {
}
return false;
}
/**
* Returns the position of the closing bracket after startPosition.
* @returns the location of the closing bracket.
* @param startPosition - the beginning position
* @param openBracket - the character that represents the open bracket
* @param closeBracket - the character that represents the close bracket
* @param document - the document being searched
*/
protected int searchForClosingBracket(int startPosition, char openBracket, char closeBracket, IDocument document) throws BadLocationException {
int stack= 1;
int closePosition= startPosition + 1;
int length= document.getLength();
char nextChar;
while (closePosition < length && stack > 0) {
nextChar= document.getChar(closePosition);
if (nextChar == openBracket && nextChar != closeBracket)
stack++;
else if (nextChar == closeBracket)
stack--;
closePosition++;
}
if (stack == 0)
return closePosition - 1;
else
return -1;
}
/**
* Returns the position of the open bracket before startPosition.
* @returns the location of the starting bracket.
* @param startPosition - the beginning position
* @param openBracket - the character that represents the open bracket
* @param closeBracket - the character that represents the close bracket
* @param document - the document being searched
*/
protected int searchForOpenBracket(int startPosition, char openBracket, char closeBracket, IDocument document) throws BadLocationException {
int stack= 1;
int openPos= startPosition - 1;
char nextChar;
while (openPos >= 0 && stack > 0) {
nextChar= document.getChar(openPos);
if (nextChar == closeBracket && nextChar != openBracket)
stack++;
else if (nextChar == openBracket)
stack--;
openPos--;
}
if (stack == 0)
return openPos + 1;
else
return -1;
}
/**
* Select the area between the selected bracket and the closing bracket. Return
* true if successful.
*/
protected boolean selectBracketBlock() {
if (matchBracketsAt()) {
if (fStartPos == fEndPos)
fText.setSelectedRange(fStartPos, 0);
else
fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1);
return true;
}
return false;
}
/**
* Select the word at the current selection.
*/
protected void selectWord() {
if (matchWord()) {
if (fStartPos == fEndPos)
fText.setSelectedRange(fStartPos, 0);
else
fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1);
}
}
}