1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-01-17 06:52:18 +01:00

Fixing double- and triple-click selection behavior (Peter Lewis)

Double clicking selects words, double-clicking and dragging does too.
Triple-click for lines.

http://code.google.com/p/arduino/issues/detail?id=824
This commit is contained in:
David A. Mellis 2012-03-02 18:06:29 -05:00
parent b133faa68f
commit a6eb9ea5eb

View File

@ -834,6 +834,17 @@ public class JEditTextArea extends JComponent
return lineElement.getEndOffset();
}
/**
* Returns the end offset of the specified line, but not past the end of the text
* @param line The line
* @return The end offset of the specified line, safe to use for a selection, or -1 if the line is
* invalid.
*/
public int getSafeLineStopOffset(int line)
{
return Math.min(getLineStopOffset(line),getDocumentLength());
}
/**
* Returns the length of the specified line.
* @param line The line
@ -1144,7 +1155,7 @@ public class JEditTextArea extends JComponent
{
throw new IllegalArgumentException("Bounds out of"
+ " range: " + newStart + "," +
newEnd);
newEnd + " [" + getDocumentLength() + "]");
}
// If the new position is the same as the old, we don't
@ -1201,6 +1212,86 @@ public class JEditTextArea extends JComponent
// getLineOfOffset(end));
}
}
private boolean isWordCharacter( char ch, String noWordSep )
{
return Character.isLetterOrDigit(ch) || ch=='_' || noWordSep.indexOf(ch) != -1;
}
protected void setNewSelectionWord( int line, int offset )
{
if (getLineLength(line) == 0) {
newSelectionStart = getLineStartOffset(line);
newSelectionEnd = newSelectionStart;
return;
}
String noWordSep = (String)document.getProperty("noWordSep");
if(noWordSep == null)
noWordSep = "";
String lineText = getLineText(line);
int wordStart = 0;
int wordEnd = lineText.length();
char ch = lineText.charAt(Math.max(0,offset - 1));
// special case for whitespace (fry 0122, bug #348)
// this is really nasty.. turns out that double-clicking any non-letter
// or digit char gets lumped together.. sooo, this quickly gets messy,
// because really it needs to check whether the chars are of the same
// type.. so a double space or double - might be grouped together,
// but what about a +=1? do + and - get grouped but not the 1? blech,
// coming back to this later. it's not a difficult fix, just a
// time-consuming one to track down all the proper cases.
/*
if (ch == ' ') {
//System.out.println("yeehaa");
for(int i = offset - 1; i >= 0; i--) {
if (lineText.charAt(i) == ' ') {
wordStart = i;
} else {
break;
}
}
for(int i = offset; i < lineText.length(); i++) {
if (lineText.charAt(i) == ' ') {
wordEnd = i + 1;
} else {
break;
}
}
} else {
*/
// If the user clicked on a non-letter char,
// we select the surrounding non-letters
boolean selectNoLetter = !isWordCharacter(ch,noWordSep);
for(int i = offset - 1; i >= 0; i--) {
ch = lineText.charAt(i);
if (selectNoLetter ^ !isWordCharacter(ch,noWordSep)) {
wordStart = i + 1;
break;
}
}
for(int i = offset; i < lineText.length(); i++) {
ch = lineText.charAt(i);
if(selectNoLetter ^ !isWordCharacter(ch,noWordSep)) {
wordEnd = i;
break;
}
}
//}
int lineStart = getLineStartOffset(line);
newSelectionStart = lineStart + wordStart;
newSelectionEnd = lineStart + wordEnd;
}
/**
@ -1684,6 +1775,14 @@ public class JEditTextArea extends JComponent
protected int selectionEnd;
protected int selectionEndLine;
protected boolean biasLeft;
protected int newSelectionStart; // hack to get around lack of multiple returns in Java
protected int newSelectionEnd;
protected boolean selectWord;
protected boolean selectLine;
protected int selectionAncorStart;
protected int selectionAncorEnd;
protected int bracketPosition;
protected int bracketLine;
@ -2021,9 +2120,26 @@ public class JEditTextArea extends JComponent
{
if (popup != null && popup.isVisible()) return;
setSelectionRectangular((evt.getModifiers()
& InputEvent.CTRL_MASK) != 0);
select(getMarkPosition(),xyToOffset(evt.getX(),evt.getY()));
if ( !selectWord && !selectLine ) {
setSelectionRectangular((evt.getModifiers()
& InputEvent.CTRL_MASK) != 0);
select(getMarkPosition(),xyToOffset(evt.getX(),evt.getY()));
} else {
int line = yToLine(evt.getY());
if ( selectWord ) {
setNewSelectionWord( line, xToOffset(line,evt.getX()) );
} else {
newSelectionStart = getLineStartOffset(line);
newSelectionEnd = getSafeLineStopOffset(line);
}
if ( newSelectionStart < selectionAncorStart ) {
select(newSelectionStart,selectionAncorEnd);
} else if ( newSelectionEnd > selectionAncorEnd ) {
select(selectionAncorStart,newSelectionEnd);
} else {
select(newSelectionStart,newSelectionEnd);
}
}
}
final Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR);
@ -2094,6 +2210,9 @@ public class JEditTextArea extends JComponent
int offset = xToOffset(line,evt.getX());
int dot = getLineStartOffset(line) + offset;
selectLine = false;
selectWord = false;
switch(evt.getClickCount()) {
case 1:
@ -2159,74 +2278,11 @@ public class JEditTextArea extends JComponent
bl.printStackTrace();
}
String noWordSep = (String)document.getProperty("noWordSep");
if(noWordSep == null)
noWordSep = "";
// Ok, it's not a bracket... select the word
String lineText = getLineText(line);
int wordStart = 0;
int wordEnd = lineText.length();
char ch = lineText.charAt(Math.max(0,offset - 1));
// special case for whitespace (fry 0122, bug #348)
// this is really nasty.. turns out that double-clicking any non-letter
// or digit char gets lumped together.. sooo, this quickly gets messy,
// because really it needs to check whether the chars are of the same
// type.. so a double space or double - might be grouped together,
// but what about a +=1? do + and - get grouped but not the 1? blech,
// coming back to this later. it's not a difficult fix, just a
// time-consuming one to track down all the proper cases.
/*
if (ch == ' ') {
//System.out.println("yeehaa");
for(int i = offset - 1; i >= 0; i--) {
if (lineText.charAt(i) == ' ') {
wordStart = i;
} else {
break;
}
}
for(int i = offset; i < lineText.length(); i++) {
if (lineText.charAt(i) == ' ') {
wordEnd = i + 1;
} else {
break;
}
}
} else {
*/
// If the user clicked on a non-letter char,
// we select the surrounding non-letters
boolean selectNoLetter = (!Character.isLetterOrDigit(ch)
&& noWordSep.indexOf(ch) == -1);
for(int i = offset - 1; i >= 0; i--) {
ch = lineText.charAt(i);
if (selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
noWordSep.indexOf(ch) == -1)) {
wordStart = i + 1;
break;
}
}
for(int i = offset; i < lineText.length(); i++) {
ch = lineText.charAt(i);
if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
noWordSep.indexOf(ch) == -1)) {
wordEnd = i;
break;
}
}
//}
int lineStart = getLineStartOffset(line);
select(lineStart + wordStart,lineStart + wordEnd);
setNewSelectionWord( line, offset );
select(newSelectionStart,newSelectionEnd);
selectWord = true;
selectionAncorStart = selectionStart;
selectionAncorEnd = selectionEnd;
/*
String lineText = getLineText(line);
@ -2242,7 +2298,10 @@ public class JEditTextArea extends JComponent
private void doTripleClick(MouseEvent evt, int line,
int offset, int dot)
{
select(getLineStartOffset(line),getLineStopOffset(line)-1);
selectLine = true;
select(getLineStartOffset(line),getSafeLineStopOffset(line));
selectionAncorStart = selectionStart;
selectionAncorEnd = selectionEnd;
}
}