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 2009/11/05 20:19:06 UTC
svn commit: r833134 - in /incubator/pivot/trunk/wtk:
src/org/apache/pivot/wtk/TextArea.java
src/org/apache/pivot/wtk/skin/TextAreaSkin.java
test/org/apache/pivot/wtk/text/test/TextAreaTest.java
test/org/apache/pivot/wtk/text/test/document.wtkx
Author: gbrown
Date: Thu Nov 5 19:19:06 2009
New Revision: 833134
URL: http://svn.apache.org/viewvc?rev=833134&view=rev
Log:
Resolve additional selection issues in TextArea.
Modified:
incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TextArea.java
incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin.java
incubator/pivot/trunk/wtk/test/org/apache/pivot/wtk/text/test/TextAreaTest.java
incubator/pivot/trunk/wtk/test/org/apache/pivot/wtk/text/test/document.wtkx
Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TextArea.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TextArea.java?rev=833134&r1=833133&r2=833134&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TextArea.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TextArea.java Thu Nov 5 19:19:06 2009
@@ -294,9 +294,7 @@
}
if (selectionLength > 0) {
- // TODO Make this part of the undoable action (for all such
- // actions)
- document.removeRange(selectionStart, selectionLength);
+ delete(Direction.FORWARD);
}
Node descendant = document.getDescendantAt(selectionStart);
Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin.java?rev=833134&r1=833133&r2=833134&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/TextAreaSkin.java Thu Nov 5 19:19:06 2009
@@ -752,14 +752,12 @@
@Override
public void paint(Graphics2D graphics) {
// TODO DEBUG
- /*
graphics.setColor(Color.LIGHT_GRAY);
graphics.fillRect(0, 0, getWidth(), getHeight());
graphics.setColor(Color.RED);
graphics.fillRect(terminatorBounds.x, terminatorBounds.y,
terminatorBounds.width, terminatorBounds.height);
- */
super.paint(graphics);
}
@@ -773,41 +771,41 @@
public int getInsertionPoint(int x, int y) {
int offset = -1;
- for (int i = 0, n = rows.getLength(); i < n; i++) {
- Row row = rows.get(i);
-
- if (y >= row.y
- && y < row.y + row.height) {
- if (x < row.x) {
- NodeView firstNodeView = row.nodeViews.get(0);
- offset = firstNodeView.getOffset();
- } else if (x > row.x + row.width) {
- NodeView lastNodeView = row.nodeViews.get(row.nodeViews.getLength() - 1);
+ int n = rows.getLength();
+ if (n > 0) {
+ for (int i = 0; i < n; i++) {
+ Row row = rows.get(i);
- // If this is not the last row, the insertion index is the last
- // character in the row
- if (i < rows.getLength() - 1) {
- offset = lastNodeView.getOffset() + lastNodeView.getCharacterCount() - 1;
- }
- } else {
- for (NodeView nodeView : row.nodeViews) {
- Bounds nodeViewBounds = nodeView.getBounds();
+ if (y >= row.y
+ && y < row.y + row.height) {
+ if (x < row.x) {
+ NodeView firstNodeView = row.nodeViews.get(0);
+ offset = firstNodeView.getOffset();
+ } else if (x > row.x + row.width) {
+ NodeView lastNodeView = row.nodeViews.get(row.nodeViews.getLength() - 1);
+ offset = lastNodeView.getOffset() + lastNodeView.getCharacterCount();
- if (nodeViewBounds.contains(x, y)) {
- offset = nodeView.getInsertionPoint(x - nodeView.getX(), y - nodeView.getY())
- + nodeView.getOffset();
- break;
+ if (offset < getCharacterCount() - 1) {
+ offset--;
+ }
+ } else {
+ for (NodeView nodeView : row.nodeViews) {
+ Bounds nodeViewBounds = nodeView.getBounds();
+
+ if (nodeViewBounds.contains(x, y)) {
+ offset = nodeView.getInsertionPoint(x - nodeView.getX(), y - nodeView.getY())
+ + nodeView.getOffset();
+ break;
+ }
}
}
}
- }
- if (offset != -1) {
- break;
+ if (offset != -1) {
+ break;
+ }
}
- }
-
- if (offset == -1) {
+ } else {
offset = getCharacterCount() - 1;
}
@@ -873,6 +871,10 @@
// No node view contained the x position; move to the end of the row
NodeView lastNodeView = row.nodeViews.get(row.nodeViews.getLength() - 1);
offset = lastNodeView.getOffset() + lastNodeView.getCharacterCount();
+
+ if (offset < getCharacterCount() - 1) {
+ offset--;
+ }
}
}
}
@@ -1137,7 +1139,8 @@
if (glyphBounds.contains(x, y - ascent)) {
Rectangle2D glyphBounds2D = glyphBounds.getBounds2D();
- if (x - glyphBounds2D.getX() > glyphBounds2D.getWidth() / 2) {
+ if (x - glyphBounds2D.getX() > glyphBounds2D.getWidth() / 2
+ && i < n - 1) {
// The user clicked on the right half of the character; select
// the next character
i++;
@@ -1168,8 +1171,9 @@
float glyphWidth = (float)glyphBounds2D.getWidth();
if (x >= glyphX && x < glyphX + glyphWidth) {
- if (x - glyphX > glyphWidth / 2) {
- // The x position falls withing the right half of the character;
+ if (x - glyphX > glyphWidth / 2
+ && i < n - 1) {
+ // The x position falls within the right half of the character;
// select the next character
i++;
}
@@ -1334,7 +1338,7 @@
public void run() {
caretOn = !caretOn;
- if (caret != null) {
+ if (selection == null) {
TextArea textArea = (TextArea)getComponent();
textArea.repaint(caret.x, caret.y, caret.width, caret.height, true);
}
@@ -1352,10 +1356,10 @@
switch (scrollDirection) {
case FORWARD: {
// Get next offset
- int offset = getNextInsertionPoint(caretX, selectionEnd, scrollDirection);
+ int offset = getNextInsertionPoint(mouseX, selectionEnd, scrollDirection);
if (offset != -1) {
- textArea.setSelection(selectionStart, offset - selectionStart + 1);
- scrollCharacterToVisible(offset);
+ textArea.setSelection(selectionStart, offset - selectionStart);
+ scrollCharacterToVisible(offset - 1);
}
break;
@@ -1363,7 +1367,7 @@
case BACKWARD: {
// Get previous offset
- int offset = getNextInsertionPoint(caretX, selectionStart, scrollDirection);
+ int offset = getNextInsertionPoint(mouseX, selectionStart, scrollDirection);
if (offset != -1) {
textArea.setSelection(offset, selectionEnd - offset + 1);
@@ -1390,6 +1394,7 @@
private int anchor = -1;
private Direction scrollDirection = null;
+ private int mouseX = -1;
private BlinkCaretCallback blinkCaretCallback = new BlinkCaretCallback();
private ApplicationContext.ScheduledCallback scheduledBlinkCaretCallback = null;
@@ -1416,7 +1421,7 @@
Theme theme = Theme.getTheme();
font = theme.getFont();
// TODO DEBUG
- // font = new Font("Monaco", Font.PLAIN, 11);
+ font = new Font("Monaco", Font.PLAIN, 11);
color = Color.BLACK;
inactiveColor = Color.GRAY;
backgroundColor = null;
@@ -1491,11 +1496,12 @@
documentView.validate();
updateSelection();
- updateCaretX();
- showCaret(textArea.isFocused()
- && textArea.getSelectionLength() == 0);
+ caretX = caret.x;
scrollCharacterToVisible(textArea.getSelectionStart());
+
+ showCaret(textArea.isFocused()
+ && textArea.getSelectionLength() == 0);
}
}
@@ -1525,7 +1531,7 @@
graphics.translate(-margin.left, -margin.top);
// Draw the caret
- if (caret != null
+ if (selection == null
&& caretOn
&& textArea.isFocused()) {
graphics.setColor(textArea.isEditable() ? color : inactiveColor);
@@ -1541,17 +1547,16 @@
if (documentView == null) {
offset = -1;
} else {
- int width = getWidth();
int height = getHeight();
- x = Math.max(margin.left, Math.min(width - margin.right - 1, x));
+ x = Math.min(documentView.getWidth() - 1, Math.max(x - margin.left, 0));
if (y < margin.top) {
offset = documentView.getNextInsertionPoint(x, -1, Direction.FORWARD);
} else if (y > height - margin.bottom - 1) {
offset = documentView.getNextInsertionPoint(x, -1, Direction.BACKWARD);
} else {
- offset = documentView.getInsertionPoint(x - margin.left, y - margin.top);
+ offset = documentView.getInsertionPoint(x, y - margin.top);
}
}
@@ -1882,7 +1887,7 @@
}
}
- caretX = x;
+ mouseX = x;
} else {
if (Mouse.isPressed(Mouse.Button.LEFT)
&& Mouse.getCapturer() == null
@@ -1921,7 +1926,7 @@
}
}
- caretX = x;
+ caretX = caret.x;
// Set focus to the text input
textArea.requestFocus();
@@ -1946,6 +1951,7 @@
anchor = -1;
scrollDirection = null;
+ mouseX = -1;
return consumed;
}
@@ -2022,7 +2028,8 @@
textArea.setSelection(selectionStart, selectionLength);
scrollCharacterToVisible(selectionStart);
- updateCaretX();
+
+ caretX = caret.x;
consumed = true;
} else if (keyCode == Keyboard.KeyCode.RIGHT) {
@@ -2034,6 +2041,9 @@
if (selectionStart + selectionLength < document.getCharacterCount()) {
selectionLength++;
}
+
+ textArea.setSelection(selectionStart, selectionLength);
+ scrollCharacterToVisible(selectionStart + selectionLength);
} else {
// Clear the selection and move the caret forward by one
// character
@@ -2045,69 +2055,83 @@
selectionStart++;
}
- selectionLength = 0;
- }
+ textArea.setSelection(selectionStart, 0);
+ scrollCharacterToVisible(selectionStart);
- textArea.setSelection(selectionStart, selectionLength);
- scrollCharacterToVisible(selectionStart + selectionLength);
- updateCaretX();
+ caretX = caret.x;
+ }
consumed = true;
} else if (keyCode == Keyboard.KeyCode.UP) {
int selectionStart = textArea.getSelectionStart();
+
int offset = getNextInsertionPoint(caretX, selectionStart, Direction.BACKWARD);
if (offset == -1) {
- int selectionLength = textArea.getSelectionLength();
- if (selectionLength > 0
- && !Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
- textArea.setSelection(selectionStart, 0);
- scrollCharacterToVisible(selectionStart);
+ offset = 0;
+ }
- consumed = true;
- }
+ int selectionLength;
+ if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
+ int selectionEnd = selectionStart + textArea.getSelectionLength() - 1;
+ selectionLength = selectionEnd - offset + 1;
} else {
- int selectionLength;
- if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
- int selectionEnd = selectionStart + textArea.getSelectionLength() - 1;
- selectionLength = selectionEnd - offset + 1;
- } else {
- selectionLength = 0;
- }
+ selectionLength = 0;
+ }
- textArea.setSelection(offset, selectionLength);
- scrollCharacterToVisible(offset);
+ textArea.setSelection(offset, selectionLength);
+ scrollCharacterToVisible(offset);
- consumed = true;
- }
+ consumed = true;
} else if (keyCode == Keyboard.KeyCode.DOWN) {
int selectionStart = textArea.getSelectionStart();
int selectionLength = textArea.getSelectionLength();
- int selectionEnd = selectionStart + selectionLength - 1;
- int offset = getNextInsertionPoint(caretX, selectionEnd + 1, Direction.FORWARD);
+ 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;
- if (offset == -1) {
- if (selectionLength > 0
- && !Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
- textArea.setSelection(selectionEnd, 0);
- scrollCharacterToVisible(selectionEnd);
+ Bounds trailingSelectionBounds = getCharacterBounds(from);
+ x = trailingSelectionBounds.x + trailingSelectionBounds.width;
+ }
+
+ int offset = getNextInsertionPoint(x, from, Direction.FORWARD);
- consumed = true;
+ if (offset == -1) {
+ offset = documentView.getCharacterCount() - 1;
}
+
+ textArea.setSelection(selectionStart, offset - selectionStart);
+ scrollCharacterToVisible(offset);
} else {
- if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
- selectionLength = offset - selectionStart;
+ int from;
+ if (selectionLength == 0) {
+ // Get next insertion point from leading selection character
+ from = selectionStart;
} else {
- selectionStart = offset;
- selectionLength = 0;
+ // Get next insertion point from trailing selection character
+ from = selectionStart + selectionLength - 1;
}
- textArea.setSelection(selectionStart, selectionLength);
- scrollCharacterToVisible(offset);
+ int offset = getNextInsertionPoint(caretX, from, Direction.FORWARD);
- consumed = true;
+ if (offset == -1) {
+ offset = documentView.getCharacterCount() - 1;
+ }
+
+ textArea.setSelection(offset, 0);
+ scrollCharacterToVisible(offset);
}
+
+ consumed = true;
} else if (Keyboard.isPressed(commandModifier)) {
if (keyCode == Keyboard.KeyCode.A) {
textArea.setSelection(0, document.getCharacterCount());
@@ -2195,24 +2219,23 @@
// the selection will be updated in layout()
if (documentView != null
&& documentView.isValid()) {
- // Repaint any previous caret bounds
- if (caret != null) {
+ if (selection == null) {
+ // Repaint previous caret bounds
textArea.repaint(caret.x, caret.y, caret.width, caret.height);
- }
-
- // Repaint any previous selection bounds
- if (selection != null) {
+ } else {
+ // Repaint previous selection bounds
Rectangle bounds = selection.getBounds();
textArea.repaint(bounds.x, bounds.y, bounds.width, bounds.height);
}
- if (textArea.getSelectionLength() == 0) {
- updateSelection();
+ updateSelection();
+
+ if (selection == null) {
showCaret(textArea.isFocused());
} else {
- updateSelection();
showCaret(false);
+ // Repaint current selection bounds
Rectangle bounds = selection.getBounds();
textArea.repaint(bounds.x, bounds.y, bounds.width, bounds.height);
}
@@ -2242,19 +2265,17 @@
if (documentView.getCharacterCount() > 0) {
TextArea textArea = (TextArea)getComponent();
+ // Update the caret
int selectionStart = textArea.getSelectionStart();
- int selectionLength = textArea.getSelectionLength();
Bounds leadingSelectionBounds = getCharacterBounds(selectionStart);
+ caret = leadingSelectionBounds.toRectangle();
+ caret.width = 1;
- if (selectionLength == 0) {
- caret = leadingSelectionBounds.toRectangle();
- caret.width = 1;
-
- selection = null;
- } else {
- caret = null;
+ // Update the selection
+ int selectionLength = textArea.getSelectionLength();
+ if (selectionLength > 0) {
Bounds trailingSelectionBounds = getCharacterBounds(selectionStart
+ selectionLength - 1);
selection = new Area();
@@ -2286,23 +2307,16 @@
trailingSelectionBounds.x + trailingSelectionBounds.width - margin.left,
trailingSelectionBounds.height)));
}
+ } else {
+ selection = null;
}
} else {
- // Clear both the caret and the selection
- caret = null;
+ // Clear the caret and the selection
+ caret = new Rectangle();
selection = null;
}
}
- private void updateCaretX() {
- if (caret != null) {
- caretX = caret.x;
- } else if (selection != null) {
- Rectangle bounds = selection.getBounds();
- caretX = bounds.x;
- }
- }
-
private void showCaret(boolean show) {
if (scheduledBlinkCaretCallback != null) {
scheduledBlinkCaretCallback.cancel();
Modified: incubator/pivot/trunk/wtk/test/org/apache/pivot/wtk/text/test/TextAreaTest.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/test/org/apache/pivot/wtk/text/test/TextAreaTest.java?rev=833134&r1=833133&r2=833134&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/test/org/apache/pivot/wtk/text/test/TextAreaTest.java (original)
+++ incubator/pivot/trunk/wtk/test/org/apache/pivot/wtk/text/test/TextAreaTest.java Thu Nov 5 19:19:06 2009
@@ -78,6 +78,7 @@
frame = new Frame((Component)wtkxSerializer.readObject(getClass().getResource("text_area_test.wtkx")));
frame.setTitle("TextArea Test");
frame.setPreferredSize(640, 480);
+ frame.setLocation(160, 120);
frame.open(display);
textArea = (TextArea)wtkxSerializer.get("textArea");
Modified: incubator/pivot/trunk/wtk/test/org/apache/pivot/wtk/text/test/document.wtkx
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/test/org/apache/pivot/wtk/text/test/document.wtkx?rev=833134&r1=833133&r2=833134&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/test/org/apache/pivot/wtk/text/test/document.wtkx (original)
+++ incubator/pivot/trunk/wtk/test/org/apache/pivot/wtk/text/test/document.wtkx Thu Nov 5 19:19:06 2009
@@ -19,6 +19,7 @@
<Document xmlns:wtkx="http://pivot.apache.org/wtkx"
xmlns="org.apache.pivot.wtk.text">
<Paragraph>ABCD</Paragraph>
+ <Paragraph></Paragraph>
<Paragraph>1234</Paragraph>
<Paragraph>abcd</Paragraph>
<Paragraph>Pivot is an open-source platform for building rich internet applications in Java. It combines the enhanced productivity and usability features of a modern RIA toolkit with the robustness of the industry-standard Java platform.</Paragraph>