@Override
public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
boolean consumed = false;
if (paragraphViews.getLength() > 0) {
TextArea textArea = (TextArea)getComponent();
Keyboard.Modifier commandModifier = Platform.getCommandModifier();
Keyboard.Modifier wordNavigationModifier = Platform.getWordNavigationModifier();
if (keyCode == Keyboard.KeyCode.ENTER
&& textArea.isEditable()
&& Keyboard.getModifiers() == 0) {
int index = textArea.getSelectionStart();
textArea.removeText(index, textArea.getSelectionLength());
textArea.insertText("\n", index);
consumed = true;
} else if (keyCode == Keyboard.KeyCode.DELETE
&& textArea.isEditable()) {
int index = textArea.getSelectionStart();
if (index < textArea.getCharacterCount()) {
int count = Math.max(textArea.getSelectionLength(), 1);
textArea.removeText(index, count);
consumed = true;
}
} else if (keyCode == Keyboard.KeyCode.BACKSPACE
&& textArea.isEditable()) {
int index = textArea.getSelectionStart();
int count = textArea.getSelectionLength();
if (count == 0
&& index > 0) {
textArea.removeText(index - 1, 1);
consumed = true;
} else {
textArea.removeText(index, count);
consumed = true;
}
} else if (keyCode == Keyboard.KeyCode.TAB
&& Keyboard.isPressed(Keyboard.Modifier.CTRL)
&& textArea.isEditable()) {
int selectionLength = textArea.getSelectionLength();
StringBuilder tabBuilder = new StringBuilder();
for (int i = 0; i < 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);
}
showCaret(true);
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
int selectionStart = textArea.getSelectionStart();
int selectionLength = textArea.getSelectionLength();
int rowOffset = getRowOffset(selectionStart);
if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
selectionLength += selectionStart - rowOffset;
}
if (selectionStart >= 0) {
textArea.setSelection(rowOffset, selectionLength);
scrollCharacterToVisible(rowOffset);
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
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;
} else {
selectionStart = rowOffset + rowLength;
if (textArea.getCharacterAt(selectionStart) != '\n') {
selectionStart--;
}
selectionLength = 0;
}
if (selectionStart + selectionLength <= textArea.getCharacterCount()) {
textArea.setSelection(selectionStart, selectionLength);
scrollCharacterToVisible(selectionStart + selectionLength);
caretX = caret.x;
if (selection != null) {
caretX += selection.getBounds2D().getWidth();
}
consumed = true;
}
} else if (keyCode == Keyboard.KeyCode.LEFT) {
int selectionStart = textArea.getSelectionStart();
int selectionLength = textArea.getSelectionLength();
if (Keyboard.isPressed(wordNavigationModifier)) {
// Move the caret to the start of the next word to the left
if (selectionStart > 0) {
// Skip over any space immediately to the left
int index = selectionStart;
while (index > 0
&& Character.isWhitespace(textArea.getCharacterAt(index - 1))) {
index--;
}
// Skip over any word-letters to the left
while (index > 0
&& !Character.isWhitespace(textArea.getCharacterAt(index - 1))) {
index--;
}
if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
selectionLength += selectionStart - index;
} else {
selectionLength = 0;
}
selectionStart = index;
}
} else if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
// Add the previous character to the selection
if (selectionStart > 0) {
selectionStart--;
selectionLength++;
}
} else {
// Move the caret back by one character
if (selectionLength == 0
&& selectionStart > 0) {
selectionStart--;
}
// Clear the selection
selectionLength = 0;
}
if (selectionStart >= 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(wordNavigationModifier)) {
// Move the caret to the start of the next word to the right
if (selectionStart < textArea.getCharacterCount()) {
int index = selectionStart + selectionLength;
// Skip over any space immediately to the right
while (index < textArea.getCharacterCount()
&& Character.isWhitespace(textArea.getCharacterAt(index))) {
index++;
}
// Skip over any word-letters to the right
while (index < textArea.getCharacterCount()
&& !Character.isWhitespace(textArea.getCharacterAt(index))) {
index++;
}
if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
selectionLength = index - selectionStart;
} else {
selectionStart = index;
selectionLength = 0;
}
}
} else if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
// Add the next character to the selection
selectionLength++;
} else {
// Move the caret forward by one character
if (selectionLength == 0) {
selectionStart++;
} else {
selectionStart += selectionLength;
}
// Clear the selection
selectionLength = 0;
}
if (selectionStart + selectionLength <= textArea.getCharacterCount()) {
textArea.setSelection(selectionStart, selectionLength);
scrollCharacterToVisible(selectionStart + selectionLength);
caretX = caret.x;
if (selection != null) {
caretX += selection.getBounds2D().getWidth();
}
consumed = true;
}
} else if (keyCode == Keyboard.KeyCode.UP) {
int selectionStart = textArea.getSelectionStart();
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;
} else {
selectionLength = 0;
}
textArea.setSelection(index, selectionLength);
scrollCharacterToVisible(index);
}
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 index = getNextInsertionPoint(x, from, TextArea.ScrollDirection.DOWN);
if (index != -1) {
// If the next character is a paragraph terminator and is
// not the final terminator character, increment the selection
if (index < textArea.getCharacterCount() - 1
&& textArea.getCharacterAt(index) == '\n') {
index++;
}
textArea.setSelection(selectionStart, index - selectionStart);
scrollCharacterToVisible(index);
}
} 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 index = getNextInsertionPoint(caretX, from, TextArea.ScrollDirection.DOWN);
if (index != -1) {
textArea.setSelection(index, 0);
scrollCharacterToVisible(index);
}
}
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();
}
consumed = true;
}
} else {