📄 textareacomposer.java
字号:
package com.jmobilecore.ui.core;
import javax.microedition.lcdui.Font;
import java.util.Vector;
/**
* The <code>TextAreaText</code> defines set of methods
* that supports a text caret's handling and basic text editing.
*
* @author Evgeniy Krapiva
* @author Greg Gridin
*/
public class TextAreaComposer implements AbstractComposer {
/**
* <code>LineRange</code> represents 2 numbers - ranges for displayed text
*/
static public class LineRange {
public int from;
public int to;
public LineRange(int from, int to) {
this.from = from;
this.to = to;
}
}
/**
* Current wrapping style
*/
public byte wrappingStyle = TextArea.WORD_WRAPPING;
/**
* Current caret position in characters from the beginning of text
*/
protected int caretPosition = 0;
/**
* Current caret position from the beginning of a row
*/
protected int caretPositionX = 0;
/**
* The caret vertical position from the top of component
*/
protected int caretPositionY = 0;
/**
* Holds the LineRange classes. Total number of rows the flat text
* is splitted into equals linebreaks.size()
*/
protected Vector linebreaks;
/**
* Current row where the caret is situated
*/
protected LineRange currentRange;
/**
* The text to edit
*/
protected StringBuffer text;
/**
* The number of rows
*/
int nRows;
/**
* The work area width
*/
int componentWidth;
/**
* The first of the visible rows
*/
int startRow = 0;
/**
* Text font
*/
private Font font;
/**
* Constructs new instance of <code>TextAreaText</code>.
*
* @param rows the number of rows to display
* @param compwidth
* @param font the current font
*/
public TextAreaComposer(int rows, int compwidth, Font font) {
text = new StringBuffer();
linebreaks = new Vector();
nRows = rows;
componentWidth = compwidth;
this.font = font;
startRow = 0;
caretPosition = 0;
caretPositionX = 0;
caretPositionY = 0;
currentRange = new LineRange(0, 0);
}
/**
* Splits the text onto displayable substrings
*/
public void indexText() {
final int length = text.length();
linebreaks.removeAllElements();
if (length == 0) return;
if (wrappingStyle == TextArea.SYMBOL_WRAPPING) {
String temp;
int p = 0, oldp = 0;
//start the splitting
while (true) {
oldp = p;
do {
p++;
if (p > text.length()) break; //previous symbol was final
temp = text.toString().substring(oldp, p);
} while (font.stringWidth(temp) <= componentWidth);
addLine(oldp, p - 1); //add the substring
if (p > text.length()) break; //if complete then exit
p = p - 1;
}
} else if (wrappingStyle == TextArea.WORD_WRAPPING) {
int start = 0, end = 0, lastSpace = -1;
int curWidth = Style.H_GAP;
char ch;
for (int pos = 0; pos < length; pos++) {
ch = text.charAt(pos);
if (ch == '\n') {
addLine(start, pos);
curWidth = Style.H_GAP;
//text.setCharAt(pos,' ');
lastSpace = start = pos + 1;
continue;
}
if (ch == ' ') {
lastSpace = pos;
if (start == pos) {
start++;
continue;
}
}
curWidth += font.charWidth(ch);
if (curWidth >= componentWidth) {
end = (lastSpace > start) ? lastSpace + 1 : pos;
addLine(start, end);
curWidth = Style.H_GAP;
lastSpace = start = end;
pos = end - 1;
}
}
addLine(start, length);
}
}
/**
* Adds the line
*/
private void addLine(int from, int to) {
linebreaks.addElement(new LineRange(from, to));
}
/**
* Moves the caret one position left
*
* @return <code>true</code> if the moving is possible/done, <code>false</code> otherwise
*/
public boolean caretLeft() {
return setCaretPosition(-1, 0);
}
/**
* Moves the caret one position right
*
* @return <code>true</code> if the moving is possible/done, <code>false</code> otherwise
*/
public boolean caretRight() {
return setCaretPosition(1, 0);
}
/**
* Moves the caret one position down
*
* @return <code>true</code> if the moving is possible/done, <code>false</code> otherwise
*/
protected boolean caretDown() {
return setCaretPosition(0, 1);
}
/**
* Moves the caret one position up
*
* @return <code>true</code> if the moving is possible/done, <code>false</code> otherwise
*/
protected boolean caretUp() {
return setCaretPosition(0, -1);
}
/**
* Moves the caret in horizontal and vertical directions
*
* @param hDirection the horizontal offset
* @param vDirection the vertical offset
* @return <code>true</code> if move is complete, <code>false</code> if move failed
*/
private boolean setCaretPosition(int hDirection, int vDirection) {
int size = linebreaks.size();
//if caretLeft or CaretRight
if (vDirection == 0) {
caretPosition = caretPosition + hDirection; //set new value of caretPosition
if (caretPosition < 0) {
caretPosition = 0;
return false;
}
if (caretPosition > text.length()) {
caretPosition = text.length();
return false;
}
//lets locate the range where the caret is
int r = findRange(caretPosition);
if (r == -1) return false;
currentRange = (LineRange) linebreaks.elementAt(r);
//the caret can be on empty space after the final symbol in final substring only
//in other cases caters moves to next line
if (caretPosition == currentRange.to && r != size - 1)
currentRange = (LineRange) linebreaks.elementAt(++r);
//lets set caret offset from beginning of the line
caretPositionX = caretPosition - currentRange.from;
//if caret moves to next line then
if (startRow + caretPositionY != r) {
//add to caretPositionY the direction of caret offset
caretPositionY += r - (startRow + caretPositionY);
//if caret is located on following line then
if (caretPositionY >= nRows) {
startRow++; //start drawing from then next line
caretPositionY--; //but caret stays on the last line
}
//if caret is located on preceding line then
else if (caretPositionY < 0) {
if (startRow > 0) startRow--; //start drawing from then previous line
caretPositionY++; //but caret stays on the first line
}
} //end if
} //end of caretLeft/caretRight processing
//***************************************************************************************88
//if caretUp, caretDown
if (vDirection != 0 && size != 0) {
//set new value of caretPosition
caretPositionY = caretPositionY + vDirection;
// if caretDown
if (vDirection > 0) {
//if cater is on the final line then it stays there
if (caretPositionY + startRow >= size) {
caretPositionY--;
return true; //true to keep focus
}
//if caret moves to next screen
if (caretPositionY >= nRows) {
startRow++; //scroll
caretPositionY--;
}
//now we have new currentRange
try {
currentRange = (LineRange) linebreaks.elementAt(startRow + caretPositionY);
} catch (ArrayIndexOutOfBoundsException ex) {
return false;
}
}
//if caretUp
if (vDirection < 0) {
//if cater is on the first line then it stays there
if (caretPositionY < 0) {
if (startRow > 0) startRow--;
caretPositionY = 0;
}
try {
currentRange = (LineRange) linebreaks.elementAt(startRow + caretPositionY);
} catch (ArrayIndexOutOfBoundsException ex) {
return false;
}
}
//if caret position is greater than substring length
if (currentRange.from + caretPositionX > currentRange.to) {
caretPosition = currentRange.to - 1; //put the caret to end of the substring
caretPositionX = currentRange.to - currentRange.from - 1;
} else
caretPosition = currentRange.from + caretPositionX;
}
return true;
}
/**
* Deletes previous symbol, moves cursor one position left
*
* @return <code>true</code> if the delete and moving is possible/done, <code>false</code> otherwise
*/
public boolean backspace() {
if (!caretLeft()) return false;
return deleteChar();
}
/**
* Deletes current symbol
*
* @return <code>true</code> if the delete possible/done, <code>false</code> otherwise
*/
public boolean deleteChar() {
if (caretPosition < 0) return false;
if (caretPosition >= text.length()) return false;
text.deleteCharAt(caretPosition);
//if last symbol is deleted then moves caret back
if (currentRange.to - currentRange.from == 1) caretLeft();
indexText();
setCaretPosition(0, 0);
return true;
}
/**
* Adds new symbol or replaces the current one
*
* @param ch new symbol
* @param insertMode if <code>true</code> then new symbol will be added, otherwise the current symbol
* will be replaced
* @return <code>true</code> if the add/replace is possible, <code>false</code> otherwise
*/
public boolean addChar(char ch, boolean insertMode) {
if (caretPosition < 0) caretPosition = 0;
//glitch fix. If the line is missing then two frequent key presses at then end of line
// throws an exception Time range for this glitch - CURSOR_DELAY
if (!insertMode && caretPosition == text.length()) insertMode = true;
if (insertMode)
text.insert(caretPosition, ch);
else
text.setCharAt(caretPosition, ch);
indexText();
return true;
}
/**
* Returns the text that is presented by this text component.
*/
public String getText() {
return text.toString();
}
/**
* Sets the text that is presented by this
* text component to be the specified text.
*
* @param newText the new text.
*/
public void setText(String newText) {
if (newText == null) {
text = new StringBuffer();
} else {
text = new StringBuffer(newText);
}
//split the text onto substrings
indexText();
setCaretPosition(text.length());
}
/**
* Appends the given text to the text area's current text.
*/
public void appendText(String str) {
text.append(str);
//split the text onto substrings
indexText();
//apply changes
setCaretPosition(text.length());
}
/**
* Inserts the specified text at the specified position
* in this text area.
*/
public void insertText(String str, int pos) {
//inserts the text
text.insert(pos, str);
//set new position
caretPosition = pos + str.length();
//split the text onto substrings
indexText();
//apply changes
setCaretPosition(0, 0);
}
public void reset(Font font) {
this.font = font;
setText(getText());
}
/**
* Returns the range for the specified offset
*/
protected int findRange(int pos) {
int size = linebreaks.size();
LineRange range;
//Move by substrings looking for caret position
for (int i = 0; i < size; i++) {
range = (LineRange) linebreaks.elementAt(i);
//if caret belongs to this substring
if (pos >= range.from && pos <= range.to)
return i;
}
return -1; //not found
}
public int getCaretPosition() {
return caretPosition;
}
/**
* Sets cater position to specified position
*/
public boolean setCaretPosition(int pos) {
int n;
caretPosition = pos;
startRow = 0;
caretPositionY = 0;
caretPositionX = 0;
currentRange = new LineRange(0, 0);
//get substring number
n = findRange(pos);
if (n == -1) return false;
//set the currect substring
currentRange = (LineRange) linebreaks.elementAt(n);
//set starting string and cursor position
while (startRow + caretPositionY != n) {
caretPositionY++;
if (caretPositionY >= nRows) {
startRow++;
caretPositionY--;
}
}
caretPositionX = pos - currentRange.from;
return true;
}
/**
* Default destructor. Helps VM to perform garbage collection
*/
public void destructor() {
linebreaks = null;
text = null;
currentRange = null;
}
public int getCurrentLength() {
// return text.length();
return 0;
}
public char[] getChars() {
// return getText().toCharArray();
return null;
}
} // class TextAreaText
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -