You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by gb...@apache.org on 2010/09/08 20:29:11 UTC

svn commit: r995180 - in /pivot/trunk: wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraTextInputSkin.java wtk/src/org/apache/pivot/wtk/TextArea2.java wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin2.java

Author: gbrown
Date: Wed Sep  8 18:29:11 2010
New Revision: 995180

URL: http://svn.apache.org/viewvc?rev=995180&view=rev
Log:
TextAreaSkin2 updates.

Modified:
    pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraTextInputSkin.java
    pivot/trunk/wtk/src/org/apache/pivot/wtk/TextArea2.java
    pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin2.java

Modified: pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraTextInputSkin.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraTextInputSkin.java?rev=995180&r1=995179&r2=995180&view=diff
==============================================================================
--- pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraTextInputSkin.java (original)
+++ pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraTextInputSkin.java Wed Sep  8 18:29:11 2010
@@ -1040,7 +1040,9 @@ public class TerraTextInputSkin extends 
                 && textInput.getCharacterCount() == textInput.getMaximumLength()) {
                 Toolkit.getDefaultToolkit().beep();
             } else {
-                textInput.removeText(textInput.getSelectionStart(), textInput.getSelectionLength());
+                // NOTE We call getSelectionStart() explicitly here in case the remove
+                // event is vetoed
+                textInput.removeText(textInput.getSelectionStart(), selectionLength);
                 textInput.insertText(Character.toString(character), textInput.getSelectionStart());
             }
         }
@@ -1053,21 +1055,22 @@ public class TerraTextInputSkin extends 
         boolean consumed = super.keyPressed(component, keyCode, keyLocation);
 
         TextInput textInput = (TextInput)getComponent();
-
         Keyboard.Modifier commandModifier = Platform.getCommandModifier();
-        if (keyCode == Keyboard.KeyCode.DELETE
-            || keyCode == Keyboard.KeyCode.BACKSPACE) {
+
+        if (keyCode == Keyboard.KeyCode.DELETE) {
             int index = textInput.getSelectionStart();
-            int count = textInput.getSelectionLength();
-            if (count == 0) {
-                if (keyCode == Keyboard.KeyCode.BACKSPACE) {
-                    index--;
-                }
 
-                count = 1;
+            if (index >= 0) {
+                int count = Math.max(textInput.getSelectionLength(), 1);
+                textInput.removeText(index, count);
             }
 
+            consumed = true;
+        } else if (keyCode == Keyboard.KeyCode.BACKSPACE) {
+            int index = textInput.getSelectionStart() - 1;
+
             if (index >= 0) {
+                int count = Math.max(textInput.getSelectionLength(), 1);
                 textInput.removeText(index, count);
             }
 

Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/TextArea2.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/TextArea2.java?rev=995180&r1=995179&r2=995180&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/TextArea2.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/TextArea2.java Wed Sep  8 18:29:11 2010
@@ -99,34 +99,32 @@ public class TextArea2 extends Component
 
             int count = text.length();
 
-            if (count > 0) {
-                if (textArea != null
-                    && textArea.characterCount + count > textArea.maximumLength) {
-                    throw new IllegalArgumentException("Insertion of text would exceed maximum length.");
-                }
+            if (textArea != null
+                && textArea.characterCount + count > textArea.maximumLength) {
+                throw new IllegalArgumentException("Insertion of text would exceed maximum length.");
+            }
+
+            characters.insert(index, text);
 
-                characters.insert(index, text);
+            if (textArea != null) {
+                // Update offsets and character count
+                textArea.updateParagraphOffsets(textArea.paragraphs.indexOf(this) + 1, count);
+                textArea.characterCount += count;
+
+                // Update selection state
+                int previousSelectionStart = textArea.selectionStart;
+                int previousSelectionLength = textArea.selectionLength;
+                textArea.selectionStart = offset + index + count;
+                textArea.selectionLength = 0;
+
+                // Fire change events
+                paragraphListeners.textInserted(this, index, count);
+                textArea.textAreaContentListeners.textChanged(textArea);
 
-                if (textArea != null) {
-                    // Update offsets and character count
-                    textArea.updateParagraphOffsets(textArea.paragraphs.indexOf(this) + 1, count);
-                    textArea.characterCount += count;
-
-                    // Update selection state
-                    int previousSelectionStart = textArea.selectionStart;
-                    int previousSelectionLength = textArea.selectionLength;
-                    textArea.selectionStart = offset + index + count;
-                    textArea.selectionLength = 0;
-
-                    // Fire change events
-                    paragraphListeners.textInserted(this, index, count);
-                    textArea.textAreaContentListeners.textChanged(textArea);
-
-                    if (textArea.selectionStart != previousSelectionStart
-                        || textArea.selectionLength != previousSelectionLength) {
-                        textArea.textAreaSelectionListeners.selectionChanged(textArea,
-                            textArea.selectionStart, textArea.selectionLength);
-                    }
+                if (textArea.selectionStart != previousSelectionStart
+                    || textArea.selectionLength != previousSelectionLength) {
+                    textArea.textAreaSelectionListeners.selectionChanged(textArea,
+                        textArea.selectionStart, textArea.selectionLength);
                 }
             }
         }
@@ -141,29 +139,27 @@ public class TextArea2 extends Component
                 throw new IndexOutOfBoundsException();
             }
 
-            if (count > 0) {
-                characters.delete(index, index + count);
+            characters.delete(index, index + count);
+
+            if (textArea != null) {
+                // Update offsets and character count
+                textArea.updateParagraphOffsets(textArea.paragraphs.indexOf(this) + 1, -count);
+                textArea.characterCount -= count;
+
+                // Update selection state
+                int previousSelectionStart = textArea.selectionStart;
+                int previousSelectionLength = textArea.selectionLength;
+                textArea.selectionStart = offset + index;
+                textArea.selectionLength = 0;
 
-                if (textArea != null) {
-                    // Update offsets and character count
-                    textArea.updateParagraphOffsets(textArea.paragraphs.indexOf(this) + 1, -count);
-                    textArea.characterCount -= count;
-
-                    // Update selection state
-                    int previousSelectionStart = textArea.selectionStart;
-                    int previousSelectionLength = textArea.selectionLength;
-                    textArea.selectionStart = offset + index;
-                    textArea.selectionLength = 0;
-
-                    // Fire change events
-                    paragraphListeners.textRemoved(this, index, count);
-                    textArea.textAreaContentListeners.textChanged(textArea);
-
-                    if (textArea.selectionStart != previousSelectionStart
-                        || textArea.selectionLength != previousSelectionLength) {
-                        textArea.textAreaSelectionListeners.selectionChanged(textArea,
-                            textArea.selectionStart, textArea.selectionLength);
-                    }
+                // Fire change events
+                paragraphListeners.textRemoved(this, index, count);
+                textArea.textAreaContentListeners.textChanged(textArea);
+
+                if (textArea.selectionStart != previousSelectionStart
+                    || textArea.selectionLength != previousSelectionLength) {
+                    textArea.textAreaSelectionListeners.selectionChanged(textArea,
+                        textArea.selectionStart, textArea.selectionLength);
                 }
             }
         }
@@ -698,7 +694,7 @@ public class TextArea2 extends Component
                     int count = paragraph.characters.length();
 
                     CharSequence trailingCharacters = paragraph.characters.subSequence(characterOffset, count);
-                    paragraph.removeText(characterOffset, count);
+                    paragraph.removeText(characterOffset, count - characterOffset);
                     paragraph.insertText(textBuilder, characterOffset);
 
                     paragraph = new Paragraph();
@@ -752,9 +748,11 @@ public class TextArea2 extends Component
     }
 
     private void updateParagraphOffsets(int from, int count) {
-        for (int i = from, n = paragraphs.getLength(); i < n; i++) {
-            Paragraph paragraph = paragraphs.get(i);
-            paragraph.offset += count;
+        if (count > 0) {
+            for (int i = from, n = paragraphs.getLength(); i < n; i++) {
+                Paragraph paragraph = paragraphs.get(i);
+                paragraph.offset += count;
+            }
         }
     }
 

Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin2.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin2.java?rev=995180&r1=995179&r2=995180&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin2.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin2.java Wed Sep  8 18:29:11 2010
@@ -21,6 +21,7 @@ import java.awt.Font;
 import java.awt.Graphics2D;
 import java.awt.Rectangle;
 import java.awt.Shape;
+import java.awt.Toolkit;
 import java.awt.Transparency;
 import java.awt.font.FontRenderContext;
 import java.awt.font.GlyphVector;
@@ -373,6 +374,7 @@ public class TextAreaSkin2 extends Compo
     private ArrayList<ParagraphView> paragraphViews = new ArrayList<ParagraphView>();
 
     private static final int PARAGRAPH_TERMINATOR_WIDTH = 2;
+    private static final int SCROLL_RATE = 30;
 
     public TextAreaSkin2() {
         Theme theme = Theme.getTheme();
@@ -839,7 +841,55 @@ public class TextAreaSkin2 extends Compo
     public boolean mouseMove(Component component, int x, int y) {
         boolean consumed = super.mouseMove(component, x, y);
 
-        // TODO
+        if (Mouse.getCapturer() == component) {
+            TextArea2 textArea = (TextArea2)getComponent();
+
+            Bounds visibleArea = textArea.getVisibleArea();
+            visibleArea = new Bounds(visibleArea.x, visibleArea.y,
+                visibleArea.width, visibleArea.height);
+
+            if (y >= visibleArea.y
+                && y < visibleArea.y + visibleArea.height) {
+                // Stop the scroll selection timer
+                if (scheduledScrollSelectionCallback != null) {
+                    scheduledScrollSelectionCallback.cancel();
+                    scheduledScrollSelectionCallback = null;
+                }
+
+                scrollDirection = null;
+                int offset = getInsertionPoint(x, y);
+
+                if (offset != -1) {
+                    // Select the range
+                    if (offset > anchor) {
+                        textArea.setSelection(anchor, offset - anchor);
+                    } else {
+                        textArea.setSelection(offset, anchor - offset);
+                    }
+                }
+            } else {
+                if (scheduledScrollSelectionCallback == null) {
+                    scrollDirection = (y < visibleArea.y) ?
+                        TextArea2.ScrollDirection.UP : TextArea2.ScrollDirection.DOWN;
+
+                    scheduledScrollSelectionCallback =
+                        ApplicationContext.scheduleRecurringCallback(scrollSelectionCallback,
+                            SCROLL_RATE);
+
+                    // Run the callback once now to scroll the selection immediately
+                    scrollSelectionCallback.run();
+                }
+            }
+
+            mouseX = x;
+        } else {
+            if (Mouse.isPressed(Mouse.Button.LEFT)
+                && Mouse.getCapturer() == null
+                && anchor != -1) {
+                // Capture the mouse so we can select text
+                Mouse.capture(component);
+            }
+        }
 
         return consumed;
     }
@@ -848,7 +898,33 @@ public class TextAreaSkin2 extends Compo
     public boolean mouseDown(Component component, Mouse.Button button, int x, int y) {
         boolean consumed = super.mouseDown(component, button, x, y);
 
-        // TODO
+        if (button == Mouse.Button.LEFT) {
+            TextArea2 textArea = (TextArea2)component;
+
+            anchor = getInsertionPoint(x, y);
+
+            if (anchor != -1) {
+                if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+                    // Select the range
+                    int selectionStart = textArea.getSelectionStart();
+
+                    if (anchor > selectionStart) {
+                        textArea.setSelection(selectionStart, anchor - selectionStart);
+                    } else {
+                        textArea.setSelection(anchor, selectionStart - anchor);
+                    }
+                } else {
+                    // Move the caret to the insertion point
+                    textArea.setSelection(anchor, 0);
+                    consumed = true;
+                }
+            }
+
+            caretX = caret.x;
+
+            // Set focus to the text input
+            textArea.requestFocus();
+        }
 
         return consumed;
     }
@@ -857,7 +933,19 @@ public class TextAreaSkin2 extends Compo
     public boolean mouseUp(Component component, Mouse.Button button, int x, int y) {
         boolean consumed = super.mouseUp(component, button, x, y);
 
-        // TODO
+        if (Mouse.getCapturer() == component) {
+            // Stop the scroll selection timer
+            if (scheduledScrollSelectionCallback != null) {
+                scheduledScrollSelectionCallback.cancel();
+                scheduledScrollSelectionCallback = null;
+            }
+
+            Mouse.release();
+        }
+
+        anchor = -1;
+        scrollDirection = null;
+        mouseX = -1;
 
         return consumed;
     }
@@ -866,16 +954,283 @@ public class TextAreaSkin2 extends Compo
     public boolean keyTyped(Component component, char character) {
         boolean consumed = super.keyTyped(component, character);
 
-        // TODO
+        TextArea2 textArea = (TextArea2)getComponent();
+
+        if (textArea.isEditable()) {
+            // Ignore characters in the control range and the ASCII delete
+            // character as well as meta key presses
+            if (character > 0x1F
+                && character != 0x7F
+                && !Keyboard.isPressed(Keyboard.Modifier.META)) {
+                int selectionLength = textArea.getSelectionLength();
+
+                if (selectionLength == 0
+                    && textArea.getCharacterCount() == textArea.getMaximumLength()) {
+                    Toolkit.getDefaultToolkit().beep();
+                } else {
+                    int selectionStart = textArea.getSelectionStart();
+                    textArea.removeText(selectionStart, selectionLength);
+                    textArea.insertText(Character.toString(character), selectionStart);
+                }
+
+                showCaret(true);
+            }
+        }
 
         return consumed;
     }
 
     @Override
     public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
-        boolean consumed = super.keyPressed(component, keyCode, keyLocation);
+        boolean consumed = false;
 
-        // TODO
+        TextArea2 textArea = (TextArea2)getComponent();
+        Keyboard.Modifier commandModifier = Platform.getCommandModifier();
+
+        if (keyCode == Keyboard.KeyCode.ENTER
+            && textArea.isEditable()) {
+            int index = textArea.getSelectionStart();
+            textArea.removeText(index, textArea.getSelectionLength());
+            textArea.insertText("\n", index);
+
+            consumed = true;
+        } else if (keyCode == Keyboard.KeyCode.DELETE) {
+            int index = textArea.getSelectionStart();
+
+            if (index >= 0) {
+                int count = Math.max(textArea.getSelectionLength(), 1);
+                textArea.removeText(index, count);
+            }
+
+            consumed = true;
+        } else if (keyCode == Keyboard.KeyCode.BACKSPACE) {
+            int index = textArea.getSelectionStart() - 1;
+
+            if (index >= 0) {
+                int count = Math.max(textArea.getSelectionLength(), 1);
+                textArea.removeText(index, count);
+            }
+
+            consumed = true;
+        } else if (keyCode == Keyboard.KeyCode.LEFT) {
+            int selectionStart = textArea.getSelectionStart();
+            int selectionLength = textArea.getSelectionLength();
+
+            if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+                // Add the previous character to the selection
+                if (selectionStart > 0) {
+                    selectionStart--;
+                    selectionLength++;
+                }
+            } else if (Keyboard.isPressed(Keyboard.Modifier.CTRL)) {
+                // Move the caret to the start of the next word to our left
+                if (selectionStart > 0) {
+                    // Skip over any space immediately to the left
+                    while (selectionStart > 0
+                        && Character.isWhitespace(textArea.getCharacterAt(selectionStart - 1))) {
+                        selectionStart--;
+                    }
+
+                    // Skip over any word-letters to our left
+                    while (selectionStart > 0
+                        && !Character.isWhitespace(textArea.getCharacterAt(selectionStart - 1))) {
+                        selectionStart--;
+                    }
+
+                    selectionLength = 0;
+                }
+            } else {
+                // Clear the selection and move the caret back by one character
+                if (selectionLength == 0
+                    && selectionStart > 0) {
+                    selectionStart--;
+                }
+
+                selectionLength = 0;
+            }
+
+            textArea.setSelection(selectionStart, selectionLength);
+            scrollCharacterToVisible(selectionStart);
+
+            caretX = caret.x;
+
+            consumed = true;
+        } else if (keyCode == Keyboard.KeyCode.RIGHT) {
+            int selectionStart = textArea.getSelectionStart();
+            int selectionLength = textArea.getSelectionLength();
+
+            if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+                // Add the next character to the selection
+                if (selectionStart + selectionLength < textArea.getCharacterCount()) {
+                    selectionLength++;
+                }
+
+                textArea.setSelection(selectionStart, selectionLength);
+                scrollCharacterToVisible(selectionStart + selectionLength);
+            } else if (Keyboard.isPressed(Keyboard.Modifier.CTRL)) {
+                // Move the caret to the start of the next word to our right
+                if (selectionStart < textArea.getCharacterCount()) {
+                    // first, skip over any word-letters to our right
+                    while (selectionStart < textArea.getCharacterCount() - 1
+                            && !Character.isWhitespace(textArea.getCharacterAt(selectionStart))) {
+                        selectionStart++;
+                    }
+                    // then, skip over any space immediately to our right
+                    while (selectionStart < textArea.getCharacterCount() - 1
+                            && Character.isWhitespace(textArea.getCharacterAt(selectionStart))) {
+                        selectionStart++;
+                    }
+
+                    textArea.setSelection(selectionStart, 0);
+                    scrollCharacterToVisible(selectionStart);
+
+                    caretX = caret.x;
+                }
+            } else {
+                // Clear the selection and move the caret forward by one
+                // character
+                if (selectionLength > 0) {
+                    selectionStart += selectionLength - 1;
+                }
+
+                if (selectionStart < textArea.getCharacterCount() - 1) {
+                    selectionStart++;
+                }
+
+                textArea.setSelection(selectionStart, 0);
+                scrollCharacterToVisible(selectionStart);
+
+                caretX = caret.x;
+            }
+
+            consumed = true;
+        } else if (keyCode == Keyboard.KeyCode.UP) {
+            int selectionStart = textArea.getSelectionStart();
+
+            int offset = getNextInsertionPoint(caretX, selectionStart, TextArea2.ScrollDirection.UP);
+
+            if (offset == -1) {
+                offset = 0;
+            }
+
+            int selectionLength;
+            if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+                int selectionEnd = selectionStart + textArea.getSelectionLength() - 1;
+                selectionLength = selectionEnd - offset + 1;
+            } else {
+                selectionLength = 0;
+            }
+
+            textArea.setSelection(offset, selectionLength);
+            scrollCharacterToVisible(offset);
+
+            consumed = true;
+        } else if (keyCode == Keyboard.KeyCode.DOWN) {
+            int selectionStart = textArea.getSelectionStart();
+            int selectionLength = textArea.getSelectionLength();
+
+            if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+                int from;
+                int x;
+                if (selectionLength == 0) {
+                    // Get next insertion point from leading selection character
+                    from = selectionStart;
+                    x = caretX;
+                } else {
+                    // Get next insertion point from right edge of trailing selection
+                    // character
+                    from = selectionStart + selectionLength - 1;
+
+                    Bounds trailingSelectionBounds = getCharacterBounds(from);
+                    x = trailingSelectionBounds.x + trailingSelectionBounds.width;
+                }
+
+                int offset = getNextInsertionPoint(x, from, TextArea2.ScrollDirection.DOWN);
+
+                if (offset == -1) {
+                    offset = textArea.getCharacterCount() - 1;
+                } else {
+                    // If the next character is a paragraph terminator and is not the
+                    // final terminator character, increment the selection
+                    if (textArea.getCharacterAt(offset) == '\n'
+                        && offset < textArea.getCharacterCount() - 1) {
+                        offset++;
+                    }
+                }
+
+                textArea.setSelection(selectionStart, offset - selectionStart);
+                scrollCharacterToVisible(offset);
+            } else {
+                int from;
+                if (selectionLength == 0) {
+                    // Get next insertion point from leading selection character
+                    from = selectionStart;
+                } else {
+                    // Get next insertion point from trailing selection character
+                    from = selectionStart + selectionLength - 1;
+                }
+
+                int offset = getNextInsertionPoint(caretX, from, TextArea2.ScrollDirection.DOWN);
+
+                if (offset == -1) {
+                    offset = textArea.getCharacterCount() - 1;
+                }
+
+                textArea.setSelection(offset, 0);
+                scrollCharacterToVisible(offset);
+            }
+
+            consumed = true;
+        } else if (Keyboard.isPressed(commandModifier)) {
+            if (keyCode == Keyboard.KeyCode.A) {
+                textArea.setSelection(0, textArea.getCharacterCount());
+                consumed = true;
+            } else if (keyCode == Keyboard.KeyCode.X
+                && textArea.isEditable()) {
+                textArea.cut();
+                consumed = true;
+            } else if (keyCode == Keyboard.KeyCode.C) {
+                textArea.copy();
+                consumed = true;
+            } else if (keyCode == Keyboard.KeyCode.V
+                && textArea.isEditable()) {
+                textArea.paste();
+                consumed = true;
+            } else if (keyCode == Keyboard.KeyCode.Z
+                && textArea.isEditable()) {
+                if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+                    textArea.undo();
+                } else {
+                    textArea.redo();
+                }
+
+                consumed = true;
+            }
+        } else if (keyCode == Keyboard.KeyCode.HOME) {
+            // Move the caret to the beginning of the text
+            if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+                textArea.setSelection(0, textArea.getSelectionStart());
+            } else {
+                textArea.setSelection(0, 0);
+            }
+            scrollCharacterToVisible(0);
+
+            consumed = true;
+        } else if (keyCode == Keyboard.KeyCode.END) {
+            // Move the caret to the end of the text
+            if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+                int selectionStart = textArea.getSelectionStart();
+                textArea.setSelection(selectionStart, textArea.getCharacterCount()
+                    - selectionStart);
+            } else {
+                textArea.setSelection(textArea.getCharacterCount() - 1, 0);
+            }
+            scrollCharacterToVisible(textArea.getCharacterCount() - 1);
+
+            consumed = true;
+        } else {
+            consumed = super.keyPressed(component, keyCode, keyLocation);
+        }
 
         return consumed;
     }