Skip to content

Commit

Permalink
Fixing double- and triple-click selection behavior (Peter Lewis)
Browse files Browse the repository at this point in the history
Double clicking selects words, double-clicking and dragging does too.
Triple-click for lines.

http://code.google.com/p/arduino/issues/detail?id=824
  • Loading branch information
damellis committed Mar 2, 2012
1 parent b133faa commit a6eb9ea
Showing 1 changed file with 132 additions and 73 deletions.
205 changes: 132 additions & 73 deletions app/src/processing/app/syntax/JEditTextArea.java
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,17 @@ public int getLineStopOffset(int line)
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
Expand Down Expand Up @@ -1144,7 +1155,7 @@ public void select(int start, int end)
{
throw new IllegalArgumentException("Bounds out of"
+ " range: " + newStart + "," +
newEnd);
newEnd + " [" + getDocumentLength() + "]");
}

// If the new position is the same as the old, we don't
Expand Down Expand Up @@ -1201,6 +1212,86 @@ public void select(int start, int end)
// 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;
}


/**
Expand Down Expand Up @@ -1684,6 +1775,14 @@ public void processKeyEvent(KeyEvent evt) {
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;
Expand Down Expand Up @@ -2021,9 +2120,26 @@ public void mouseDragged(MouseEvent evt)
{
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);
Expand Down Expand Up @@ -2094,6 +2210,9 @@ public void mousePressed(MouseEvent evt)
int offset = xToOffset(line,evt.getX());
int dot = getLineStartOffset(line) + offset;

selectLine = false;
selectWord = false;

switch(evt.getClickCount()) {

case 1:
Expand Down Expand Up @@ -2159,74 +2278,11 @@ private void doDoubleClick(MouseEvent evt, int line,
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);
Expand All @@ -2242,7 +2298,10 @@ private void doDoubleClick(MouseEvent evt, int line,
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;
}
}

Expand Down

0 comments on commit a6eb9ea

Please sign in to comment.