You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by rw...@apache.org on 2013/02/14 18:55:01 UTC

svn commit: r1446283 - /pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin.java

Author: rwhitcomb
Date: Thu Feb 14 17:55:00 2013
New Revision: 1446283

URL: http://svn.apache.org/r1446283
Log:
Part of PIVOT-891: Implement double-click to select a word and triple-click to
select the whole line.

Fix the Shift-LEFT and Shift-RIGHT to work "properly" in that case of first
moving in one direction and then reversing direction -- this should reduce the
selection that was just done instead of always expanding it.

The same (or similar) changes for UP/DOWN are more difficult and are eluding me
at the moment.

Also implement Ctrl-HOME moves to the beginning of the document and Ctrl-END to
the end of the document (and with Shift selects from cursor to the beginning/end).

Modified:
    pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin.java

Modified: pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin.java
URL: http://svn.apache.org/viewvc/pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin.java?rev=1446283&r1=1446282&r2=1446283&view=diff
==============================================================================
--- pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin.java (original)
+++ pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin.java Thu Feb 14 17:55:00 2013
@@ -34,6 +34,7 @@ import org.apache.pivot.collections.Sequ
 import org.apache.pivot.wtk.ApplicationContext;
 import org.apache.pivot.wtk.Bounds;
 import org.apache.pivot.wtk.Component;
+import org.apache.pivot.wtk.Cursor;
 import org.apache.pivot.wtk.Dimensions;
 import org.apache.pivot.wtk.GraphicsUtilities;
 import org.apache.pivot.wtk.Insets;
@@ -166,6 +167,8 @@ public class TextAreaSkin extends Compon
         textArea.getTextAreaListeners().add(this);
         textArea.getTextAreaContentListeners().add(this);
         textArea.getTextAreaSelectionListeners().add(this);
+
+        textArea.setCursor(Cursor.TEXT);
     }
 
     @Override
@@ -944,13 +947,80 @@ public class TextAreaSkin extends Compon
             Mouse.release();
         }
 
-        anchor = -1;
         scrollDirection = null;
         mouseX = -1;
 
         return consumed;
     }
 
+    private void selectSpan(TextArea textArea, int start) {
+        int rowStart = textArea.getRowOffset(start);
+        int rowLength = textArea.getRowLength(start);
+        if (start - rowStart >= rowLength) {
+            start = rowStart + rowLength - 1;
+            char ch = textArea.getCharacterAt(start);
+            if (ch == '\r' || ch == '\n') {
+                start--;
+            }
+        }
+        char ch = textArea.getCharacterAt(start);
+        int selectionStart = start;
+        int selectionLength = 1;
+        if (Character.isWhitespace(ch)) {
+            // Move backward to beginning of whitespace block
+            // but not before the beginning of the line.
+            do {
+                selectionStart--;
+            } while (selectionStart >= rowStart &&
+                     Character.isWhitespace(textArea.getCharacterAt(selectionStart)));
+            selectionStart++;
+            selectionLength = start - selectionStart;
+            // Move forward to end of whitespace block
+            // but not past the end of the text or the end of line
+            do {
+                selectionLength++;
+            } while (selectionStart + selectionLength - rowStart < rowLength &&
+                     Character.isWhitespace(textArea.getCharacterAt(selectionStart + selectionLength)));
+        } else if (Character.isJavaIdentifierPart(ch)) {
+            // Move backward to beginning of identifier block
+            do {
+                selectionStart--;
+            } while (selectionStart >= rowStart &&
+                     Character.isJavaIdentifierPart(textArea.getCharacterAt(selectionStart)));
+            selectionStart++;
+            selectionLength = start - selectionStart;
+            // Move forward to end of identifier block
+            // but not past end of text
+            do {
+                selectionLength++;
+            } while (selectionStart + selectionLength - rowStart < rowLength &&
+                     Character.isJavaIdentifierPart(textArea.getCharacterAt(selectionStart + selectionLength)));
+        } else {
+            return;
+        }
+        textArea.setSelection(selectionStart, selectionLength);
+    }
+
+    @Override
+    public boolean mouseClick(Component component, Mouse.Button button,
+            int x, int y, int count) {
+        boolean consumed = super.mouseClick(component, button, x, y, count);
+
+        TextArea textArea = (TextArea)component;
+
+        if (button == Mouse.Button.LEFT) {
+            int index = getInsertionPoint(x, y);
+            if (index != -1) {
+                if (count == 2) {
+                    selectSpan(textArea, index);
+                } else if (count == 3) {
+                    textArea.setSelection(textArea.getRowOffset(index), textArea.getRowLength(index));
+                }
+            }
+       }
+        return consumed;
+    }
+
     @Override
     public boolean keyTyped(Component component, char character) {
         boolean consumed = super.keyTyped(component, character);
@@ -988,12 +1058,15 @@ public class TextAreaSkin extends Compon
 
         if (paragraphViews.getLength() > 0) {
             TextArea textArea = (TextArea)getComponent();
-            Keyboard.Modifier commandModifier = Platform.getCommandModifier();
-            Keyboard.Modifier wordNavigationModifier = Platform.getWordNavigationModifier();
+            boolean commandPressed = Keyboard.isPressed(Platform.getCommandModifier());
+            boolean wordNavPressed = Keyboard.isPressed(Platform.getWordNavigationModifier());
+            boolean shiftPressed = Keyboard.isPressed(Keyboard.Modifier.SHIFT);
+            boolean ctrlPressed = Keyboard.isPressed(Keyboard.Modifier.CTRL);
+            boolean metaPressed = Keyboard.isPressed(Keyboard.Modifier.META);
+            boolean isEditable = textArea.isEditable();
 
             if (keyCode == Keyboard.KeyCode.ENTER
-                && acceptsEnter
-                && textArea.isEditable()
+                && acceptsEnter && isEditable
                 && Keyboard.getModifiers() == 0) {
                 int index = textArea.getSelectionStart();
                 textArea.removeText(index, textArea.getSelectionLength());
@@ -1001,7 +1074,7 @@ public class TextAreaSkin extends Compon
 
                 consumed = true;
             } else if (keyCode == Keyboard.KeyCode.DELETE
-                && textArea.isEditable()) {
+                && isEditable) {
                 int index = textArea.getSelectionStart();
 
                 if (index < textArea.getCharacterCount()) {
@@ -1011,7 +1084,7 @@ public class TextAreaSkin extends Compon
                     consumed = true;
                 }
             } else if (keyCode == Keyboard.KeyCode.BACKSPACE
-                && textArea.isEditable()) {
+                && isEditable) {
                 int index = textArea.getSelectionStart();
                 int count = textArea.getSelectionLength();
 
@@ -1024,19 +1097,21 @@ public class TextAreaSkin extends Compon
                     consumed = true;
                 }
             } else if (keyCode == Keyboard.KeyCode.TAB
-                && (acceptsTab != Keyboard.isPressed(Keyboard.Modifier.CTRL))
-                && textArea.isEditable()) {
+                && (acceptsTab != ctrlPressed)
+                && isEditable) {
+                int selectionStart = textArea.getSelectionStart();
                 int selectionLength = textArea.getSelectionLength();
 
+                int rowOffset = textArea.getRowOffset(selectionStart);
+                int linePos = selectionStart - rowOffset;
                 StringBuilder tabBuilder = new StringBuilder(tabWidth);
-                for (int i = 0; i < tabWidth; i++) {
+                for (int i = 0; i < tabWidth - (linePos % tabWidth); i++) {
                     tabBuilder.append(" ");
                 }
 
                 if (textArea.getCharacterCount() - selectionLength + tabWidth > textArea.getMaximumLength()) {
                     Toolkit.getDefaultToolkit().beep();
                 } else {
-                    int selectionStart = textArea.getSelectionStart();
                     textArea.removeText(selectionStart, selectionLength);
                     textArea.insertText(tabBuilder, selectionStart);
                 }
@@ -1045,40 +1120,53 @@ public class TextAreaSkin extends Compon
 
                 consumed = true;
             } else if (keyCode == Keyboard.KeyCode.HOME
-                || (keyCode == Keyboard.KeyCode.LEFT
-                    && Keyboard.isPressed(Keyboard.Modifier.META))) {
-                // Move the caret to the beginning of the line
+                || (keyCode == Keyboard.KeyCode.LEFT && metaPressed)) {
+                int start;
                 int selectionStart = textArea.getSelectionStart();
                 int selectionLength = textArea.getSelectionLength();
-                int rowOffset = getRowOffset(selectionStart);
+                if (ctrlPressed) {
+                    // Move the caret to the beginning of the text
+                    start = 0;
+                } else {
+                    // Move the caret to the beginning of the line
+                    start = getRowOffset(selectionStart);
+                }
 
-                if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
-                    selectionLength += selectionStart - rowOffset;
+                if (shiftPressed) {
+                    selectionLength += selectionStart - start;
+                } else {
+                    selectionLength = 0;
                 }
 
                 if (selectionStart >= 0) {
-                    textArea.setSelection(rowOffset, selectionLength);
-                    scrollCharacterToVisible(rowOffset);
+                    textArea.setSelection(start, selectionLength);
+                    scrollCharacterToVisible(start);
 
                     caretX = caret.x;
 
                     consumed = true;
                 }
             } else if (keyCode == Keyboard.KeyCode.END
-                || (keyCode == Keyboard.KeyCode.RIGHT
-                    && Keyboard.isPressed(Keyboard.Modifier.META))) {
-                // Move the caret to the end of the line
+                || (keyCode == Keyboard.KeyCode.RIGHT && metaPressed)) {
+                int end;
                 int selectionStart = textArea.getSelectionStart();
                 int selectionLength = textArea.getSelectionLength();
-
                 int index = selectionStart + selectionLength;
-                int rowOffset = getRowOffset(index);
-                int rowLength = getRowLength(index);
 
-                if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
-                    selectionLength += (rowOffset + rowLength) - index;
+                if (ctrlPressed) {
+                    // Move the caret to end of the text
+                    end = textArea.getCharacterCount();
+                } else {
+                    // Move the caret to the end of the line
+                    int rowOffset = getRowOffset(index);
+                    int rowLength = getRowLength(index);
+                    end = rowOffset + rowLength;
+                }
+
+                if (shiftPressed) {
+                    selectionLength += end - index;
                 } else {
-                    selectionStart = rowOffset + rowLength;
+                    selectionStart = end;
                     if (selectionStart < textArea.getCharacterCount()
                             && textArea.getCharacterAt(selectionStart) != '\n') {
                         selectionStart--;
@@ -1102,7 +1190,7 @@ public class TextAreaSkin extends Compon
                 int selectionStart = textArea.getSelectionStart();
                 int selectionLength = textArea.getSelectionLength();
 
-                if (Keyboard.isPressed(wordNavigationModifier)) {
+                if (wordNavPressed) {
                     // Move the caret to the start of the next word to the left
                     if (selectionStart > 0) {
                         // Skip over any space immediately to the left
@@ -1118,7 +1206,7 @@ public class TextAreaSkin extends Compon
                             index--;
                         }
 
-                        if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+                        if (shiftPressed) {
                             selectionLength += selectionStart - index;
                         } else {
                             selectionLength = 0;
@@ -1126,11 +1214,28 @@ public class TextAreaSkin extends Compon
 
                         selectionStart = index;
                     }
-                } else if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
-                    // Add the previous character to the selection
-                    if (selectionStart > 0) {
-                        selectionStart--;
-                        selectionLength++;
+                } else if (shiftPressed) {
+                    if (anchor != -1) {
+                        if (selectionStart < anchor) {
+                            if (selectionStart > 0) {
+                                selectionStart--;
+                                selectionLength++;
+                            }
+                        } else {
+                            if (selectionLength > 0) {
+                                selectionLength--;
+                            } else {
+                                selectionStart--;
+                                selectionLength++;
+                            }
+                        }
+                    } else {
+                        // Add the previous character to the selection
+                        anchor = selectionStart;
+                        if (selectionStart > 0) {
+                            selectionStart--;
+                            selectionLength++;
+                        }
                     }
                 } else {
                     // Move the caret back by one character
@@ -1140,6 +1245,7 @@ public class TextAreaSkin extends Compon
                     }
 
                     // Clear the selection
+                    anchor = -1;
                     selectionLength = 0;
                 }
 
@@ -1155,7 +1261,7 @@ public class TextAreaSkin extends Compon
                 int selectionStart = textArea.getSelectionStart();
                 int selectionLength = textArea.getSelectionLength();
 
-                if (Keyboard.isPressed(wordNavigationModifier)) {
+                if (wordNavPressed) {
                     // Move the caret to the start of the next word to the right
                     if (selectionStart < textArea.getCharacterCount()) {
                         int index = selectionStart + selectionLength;
@@ -1172,16 +1278,26 @@ public class TextAreaSkin extends Compon
                             index++;
                         }
 
-                        if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+                        if (shiftPressed) {
                             selectionLength = index - selectionStart;
                         } else {
                             selectionStart = index;
                             selectionLength = 0;
                         }
                     }
-                } else if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
-                    // Add the next character to the selection
-                    selectionLength++;
+                } else if (shiftPressed) {
+                    if (anchor != -1) {
+                        if (selectionStart < anchor) {
+                            selectionStart++;
+                            selectionLength--;
+                        } else {
+                            selectionLength++;
+                        }
+                    } else {
+                        // Add the next character to the selection
+                        anchor = selectionStart;
+                        selectionLength++;
+                    }
                 } else {
                     // Move the caret forward by one character
                     if (selectionLength == 0) {
@@ -1191,6 +1307,7 @@ public class TextAreaSkin extends Compon
                     }
 
                     // Clear the selection
+                    anchor = -1;
                     selectionLength = 0;
                 }
 
@@ -1207,14 +1324,13 @@ public class TextAreaSkin extends Compon
                 }
             } else if (keyCode == Keyboard.KeyCode.UP) {
                 int selectionStart = textArea.getSelectionStart();
+                int selectionLength = textArea.getSelectionLength();
 
                 int index = getNextInsertionPoint(caretX, selectionStart, TextArea.ScrollDirection.UP);
 
                 if (index != -1) {
-                    int selectionLength;
-                    if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
-                        int selectionEnd = selectionStart + textArea.getSelectionLength() - 1;
-                        selectionLength = selectionEnd - index + 1;
+                    if (shiftPressed) {
+                        selectionLength = selectionStart + selectionLength - index;
                     } else {
                         selectionLength = 0;
                     }
@@ -1228,7 +1344,7 @@ public class TextAreaSkin extends Compon
                 int selectionStart = textArea.getSelectionStart();
                 int selectionLength = textArea.getSelectionLength();
 
-                if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+                if (shiftPressed) {
                     int from;
                     int x;
                     if (selectionLength == 0) {
@@ -1276,32 +1392,33 @@ public class TextAreaSkin extends Compon
                 }
 
                 consumed = true;
-            } else if (Keyboard.isPressed(commandModifier)) {
+            } else if (commandPressed) {
                 if (keyCode == Keyboard.KeyCode.A) {
                     textArea.setSelection(0, textArea.getCharacterCount());
                     consumed = true;
                 } else if (keyCode == Keyboard.KeyCode.X
-                    && textArea.isEditable()) {
+                    && isEditable) {
                     textArea.cut();
                     consumed = true;
                 } else if (keyCode == Keyboard.KeyCode.C) {
                     textArea.copy();
                     consumed = true;
                 } else if (keyCode == Keyboard.KeyCode.V
-                    && textArea.isEditable()) {
+                    && isEditable) {
                     textArea.paste();
                     consumed = true;
                 } else if (keyCode == Keyboard.KeyCode.Z
-                    && textArea.isEditable()) {
-                    if (!Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+                    && isEditable) {
+                    if (!shiftPressed) {
                         textArea.undo();
                     }
-
                     consumed = true;
+                } else if (keyCode == Keyboard.KeyCode.TAB) {
+                    // Only here if acceptsTab is false
+                    consumed = super.keyPressed(component, keyCode, keyLocation);
                 }
             } else if (keyCode == Keyboard.KeyCode.INSERT) {
-                if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)
-                    && textArea.isEditable()) {
+                if (shiftPressed && isEditable) {
                     textArea.paste();
                     consumed = true;
                 }