Textpublic class Text extends Object Static method class use to draw and size text. |
Fields Summary |
---|
private static final char | truncationMarkCharacter to be used as a truncation indiactor,
for example, \u2026 which is ellipsis (...). | private static final int | GNL_LINE_STARTLine start. | private static final int | GNL_LINE_ENDLine end. | private static final int | GNL_NEW_LINE_STARTNew line start. | private static final int | GNL_WIDTHScreen width available. | private static final int | GNL_HEIGHTScreen height available. | private static final int | GNL_FONT_HEIGHTFont height. | private static final int | GNL_NUM_LINESLine number. | private static final int | GNL_OPTIONSText options (NORMAL, INVERT...) see below. | private static final int | GNL_OFFSETText pixel offset. | private static final int | GNL_ELLIP_WIDTHWidth of the ellipsis in the current font. | private static final int | GNL_LINE_WIDTHLine width in pixels. | private static final int | GNL_NUM_PARAMSNumber of GNL_ parameter constants. | public static final int | NORMALNORMAL text. | public static final int | INVERTINVERTED text color. | public static final int | HYPERLINKDraw a hyperlink for the text. | public static final int | TRUNCATETruncate the text and put a "..." if the text doesn't fit the bounds. | public static final int | PAINT_USE_CURSOR_INDEXWhen a paint occurs use the cursor index to know when to
paint the cursor. | public static final int | PAINT_GET_CURSOR_INDEXWhen a paint occurs try to find the best value for the cursor
index based on the x,y coordinates of the cursor. | public static final int | PAINT_HIDE_CURSORDon't draw a cursor. | public static final int | XUsed as an index into the size[], for the x. | public static final int | YUsed as an index into the size[], for the y. | public static final int | WIDTHUsed as an index into the size[], for the width. | public static final int | HEIGHTUsed as an index into the size[], for the height. |
Methods Summary |
---|
public static int | canDrawStringPart(javax.microedition.lcdui.Graphics g, java.lang.String str, int width)Given a string, determine the length of a substring that can be drawn
within the current clipping area.
If the whole string fits into the clip area,
return the length of the string.
Else, return the length of a substring (starting from the beginning
of the original string) that can be drawn within the current clipping
area before the truncation indicator.
The truncation indicator, typically, ellipsis, is not included into
the returned length.
if (width < 0) {
return 0;
}
final Font font = g.getFont();
final int stringWidth = font.stringWidth(str);
if (width >= stringWidth) {
return str.length();
}
final int widthForTruncatedText = width - font.charWidth(truncationMark);
int availableLength;
for (availableLength = str.length() - 1 ;
font.substringWidth(str,0,availableLength) > widthForTruncatedText;
availableLength-- ) {};
return availableLength;
| public static void | drawHyperLink(javax.microedition.lcdui.Graphics g, int x, int y, int w)Draws a hyperlink image.
if (StringItemSkin.IMAGE_LINK == null) {
// System.err.println("Hyperlink image is null");
return;
}
int linkHeight = StringItemSkin.IMAGE_LINK.getHeight();
int linkWidth = StringItemSkin.IMAGE_LINK.getWidth();
int oldClipX = g.getClipX();
int oldClipW = g.getClipWidth();
int oldClipY = g.getClipY();
int oldClipH = g.getClipHeight();
g.clipRect(x, oldClipY, w, oldClipH);
// Then, loop from the end of the string to the beginning,
// drawing the image as we go
for (int j = x + w - linkWidth, first = x - linkWidth;
j > first; j -= linkWidth) {
g.drawImage(StringItemSkin.IMAGE_LINK, j, y,
Graphics.BOTTOM | Graphics.LEFT);
}
g.setClip(oldClipX, oldClipY, oldClipW, oldClipH);
| public static void | drawTruncString(javax.microedition.lcdui.Graphics g, java.lang.String str, javax.microedition.lcdui.Font font, int fgColor, int width)Draw the string within the specified width.
If the string does not fit in the available width,
it is truncated at the end,
and a truncation indicator is displayed (usually,
an ellipsis, but this can be changed).
Use Graphics.translate(x,y) to specify the anchor point location
(the alignment will be TOP|LEFT relative to 0,0).
g.setFont(font);
g.setColor(fgColor);
int lengthThatCanBeShown = canDrawStringPart(g, str, width);
if (lengthThatCanBeShown == str.length()) {
g.drawString(str, 0, 0, Graphics.TOP | Graphics.LEFT);
} else {
String s = str.substring(0,lengthThatCanBeShown) + truncationMark;
g.drawString(s, 0, 0, Graphics.TOP | Graphics.LEFT);
}
| public static void | drawTruncStringShadowed(javax.microedition.lcdui.Graphics g, java.lang.String text, javax.microedition.lcdui.Font font, int fgColor, int shdColor, int shdAlign, int titlew)
int dx=1, dy=1;
// draw the shadow
if (shdColor != fgColor) {
switch (shdAlign) {
case (Graphics.TOP | Graphics.LEFT):
dx=-1;
dy=-1;
break;
case (Graphics.TOP | Graphics.RIGHT):
dx=1;
dy=-1;
break;
case (Graphics.BOTTOM | Graphics.LEFT):
dx=-1;
dy=1;
break;
case (Graphics.BOTTOM | Graphics.RIGHT):
default:
dx=1;
dy=1;
break;
}
g.translate(dx, dy);
drawTruncString(g, text, font,
shdColor, titlew);
/* if we wanted multi-line text output, we would use this:
paint(g, text, font,
shdColor, 0,
titlew, titleh, 0,
TRUNCATE, null);
*/
g.translate(-dx, -dy);
}
// now draw the text whose shadow we have drawn above
drawTruncString(g, text, font,
fgColor, titlew);
/* if we wanted multi-line text output, we would use this:
paint(g, text, font,
fgColor, 0,
titlew, titleh, 0,
TRUNCATE, null);
*/
| public static int | getHeightForWidth(java.lang.String str, javax.microedition.lcdui.Font font, int w, int offset)Gets the height in pixels to render the given string.
int[] tmpSize = new int[] {0, 0, 0, 0};
getSizeForWidth(tmpSize, w, str, font, offset);
return tmpSize[HEIGHT];
| private static boolean | getNextLine(char[] text, javax.microedition.lcdui.Font font, int[] inout)Calculates the starting and ending points for a new line of
text given the font and input parameters. Beware of the
multiple returns statements within the body.
//
// this inner loop will set lineEnd and newLineStart to
// the proper values so that a line is broken correctly
//
int curLoc = inout[GNL_LINE_START];
boolean foundBreak = false;
int leftWidth = 0;
inout[GNL_LINE_WIDTH] = 0;
int prevLineWidth = 0;
int curLineWidth = 0;
while (curLoc < text.length) {
//
// a newLine forces a break and immediately terminates
// the loop
//
// a space will be remembered as a possible place to break
//
if (text[curLoc] == '\n") {
inout[GNL_LINE_END] = curLoc;
inout[GNL_NEW_LINE_START] = curLoc + 1;
inout[GNL_LINE_WIDTH] = prevLineWidth;
return
( ((inout[GNL_OPTIONS] & TRUNCATE) == TRUNCATE)
&& ((inout[GNL_NUM_LINES] + 1) * inout[GNL_FONT_HEIGHT]
> inout[GNL_HEIGHT])
);
} else if (text[curLoc] == ' ") {
inout[GNL_LINE_END] = curLoc;
inout[GNL_NEW_LINE_START] = curLoc + 1;
inout[GNL_LINE_WIDTH] = prevLineWidth;
foundBreak = true;
}
//
// if the text is longer than one line then we
// cut the word at a word boundary if possible,
// otherwise the word is broken.
//
curLineWidth = prevLineWidth + font.charWidth(text[curLoc]);
// check up the mode is "truncate" and we reached the end of
// the last line that we can put into the specifed rectangle area
// (inout[GNL_WIDTH] x inout[GNL_HEIGHT])
if (((inout[GNL_OPTIONS] & TRUNCATE) == TRUNCATE)
&& ((inout[GNL_NUM_LINES] + 1) * inout[GNL_FONT_HEIGHT]
> inout[GNL_HEIGHT])
&& (inout[GNL_OFFSET] + curLineWidth + inout[GNL_ELLIP_WIDTH]
> inout[GNL_WIDTH])) {
leftWidth = font.charsWidth(text, curLoc + 1,
text.length - curLoc - 1);
//
// we are on the last line and at the point where
// we will need to put an ellipsis if we can't fit
// the rest of the line
//
// if the rest of the line will fit, then don't
// put an ellipsis
//
if (inout[GNL_OFFSET] + curLineWidth + leftWidth
> inout[GNL_WIDTH]) {
prevLineWidth += inout[GNL_ELLIP_WIDTH];
inout[GNL_LINE_END] = curLoc;
inout[GNL_NEW_LINE_START] = curLoc;
inout[GNL_LINE_WIDTH] = prevLineWidth;
return true;
} else {
curLineWidth += leftWidth;
inout[GNL_LINE_END] = text.length;
inout[GNL_NEW_LINE_START] = text.length;
inout[GNL_LINE_WIDTH] = curLineWidth;
return false;
}
// reached the end of the line
} else if (inout[GNL_OFFSET] + curLineWidth > inout[GNL_WIDTH]) {
if (!foundBreak) {
if (inout[GNL_OFFSET] > 0) {
// move to the next line which will have 0 offset
inout[GNL_LINE_END] = inout[GNL_LINE_START];
inout[GNL_NEW_LINE_START] = inout[GNL_LINE_START];
inout[GNL_LINE_WIDTH] = 0;
} else {
// the line is too long and we need to break it
inout[GNL_LINE_END] = curLoc;
inout[GNL_NEW_LINE_START] = curLoc;
inout[GNL_LINE_WIDTH] = prevLineWidth;
}
}
return false;
}
// go to next character
curLoc++;
prevLineWidth = curLineWidth;
} // while end
// we reach this code only if we reach the end of the text
inout[GNL_LINE_END] = text.length;
inout[GNL_NEW_LINE_START] = text.length;
inout[GNL_LINE_WIDTH] = curLineWidth;
return false;
| public static void | getSizeForWidth(int[] size, int availableWidth, java.lang.String str, javax.microedition.lcdui.Font font, int offset)Gets the height in pixels and the width of the widest line in pixels
for the given string, calculated based on the availableWidth.
size[WIDTH] and size[HEIGHT] should be set by this method.
// Case 0: null or empty string, no height
if (str == null || str.length() == 0 || availableWidth <= 0) {
size[HEIGHT] = 0;
size[WIDTH] = 0;
return;
}
char[] text = str.toCharArray();
int[] inout = initGNL(font, availableWidth, 0, Text.NORMAL, offset);
int numLines = 0;
int widest = 0;
boolean widthFound = false;
do {
numLines++;
inout[GNL_NUM_LINES] = numLines;
getNextLine(text, font, inout);
if (!widthFound) {
// a long line with no spaces
if (inout[GNL_LINE_WIDTH] > availableWidth && offset == 0) {
widest = availableWidth;
widthFound = true;
} else if (inout[GNL_LINE_WIDTH] > widest) {
widest = inout[GNL_LINE_WIDTH];
}
}
inout[GNL_LINE_START] = inout[GNL_NEW_LINE_START];
inout[GNL_OFFSET] = 0;
} while (inout[GNL_LINE_END] < text.length);
size[WIDTH] = widest;
size[HEIGHT] = font.getHeight() * numLines;
// return values in size[]
| public static void | getTwoStringsSize(int[] size, java.lang.String firstStr, java.lang.String secondStr, javax.microedition.lcdui.Font firstFont, javax.microedition.lcdui.Font secondFont, int width, int pad)Utility method to calculate the width and height in which 2
strings can fit given the strings, fonts and maximum width
in which those strings should fit. Returned width is either
the passed in width or a smaller one.
The offset in pixels for the first string is 0, second string is
laid out right after the first one with padding in between
equal to the passed in value.
The width in which both strings would fit given the maximum
is returned in size[WIDTH]. The height in which both strings
would fit is returned in size[HEIGHT];
if (((firstStr == null || firstStr.length() == 0) &&
(secondStr == null || secondStr.length() == 0)) ||
(width <= 0)) {
size[WIDTH] = size[HEIGHT] = 0;
return;
}
int[] inout = new int[GNL_NUM_PARAMS];
char[] text;
int offset = 0;
int widest = 0;
int numLines = 0;
int height = 0;
int fontHeight = 0;
if (firstStr != null && firstStr.length() > 0) {
text = firstStr.toCharArray();
fontHeight = firstFont.getHeight();
inout = initGNL(firstFont, width, 0, Text.NORMAL, 0);
do {
numLines++;
height += fontHeight;
inout[GNL_NUM_LINES] = numLines;
getNextLine(text, firstFont, inout);
if (inout[GNL_LINE_WIDTH] > widest) {
widest = inout[GNL_LINE_WIDTH];
}
inout[GNL_LINE_START] = inout[GNL_NEW_LINE_START];
} while (inout[GNL_LINE_END] < firstStr.length());
offset = inout[GNL_LINE_WIDTH];
if (secondStr == null || secondStr.length() == 0) {
// last \n in the two strings should be ignored
if (firstStr.charAt(firstStr.length() - 1) == '\n") {
height -= fontHeight;
}
size[HEIGHT] = height;
size[WIDTH] = widest;
return;
}
}
// Second string is not null and it is not empty
if (secondStr != null && secondStr.length() > 0) {
if (offset > 0) {
offset += pad;
}
text = secondStr.toCharArray();
fontHeight = secondFont.getHeight();
// Line that has the end of the first string and the beginning
// of the second one is a special one;
// We have to make sure that it is not counted twice and that
// the right font height is being added (the max of the two)
if (numLines > 0) {
numLines--;
if (inout[GNL_FONT_HEIGHT] > fontHeight) {
height -= fontHeight;
} else {
height -= inout[GNL_FONT_HEIGHT];
}
}
inout = initGNL(secondFont, width, 0, Text.NORMAL, offset);
do {
numLines++;
height += fontHeight;
inout[GNL_NUM_LINES] = numLines;
getNextLine(text, secondFont, inout);
if (inout[GNL_OFFSET] + inout[GNL_LINE_WIDTH] > widest) {
widest = inout[GNL_OFFSET] + inout[GNL_LINE_WIDTH];
}
inout[GNL_LINE_START] = inout[GNL_NEW_LINE_START];
inout[GNL_OFFSET] = 0;
} while (inout[GNL_LINE_END] < secondStr.length());
// last \n should be ignored
if (secondStr.charAt(secondStr.length() - 1) == '\n") {
height -= fontHeight;
}
}
size[WIDTH] = widest;
size[HEIGHT] = height;
return;
| public static int | getWidestLineWidth(java.lang.String str, int offset, int width, javax.microedition.lcdui.Font font)Utility method to retrieve the length of the longest line of the
text given the width. this may not necessarily be the entire
string if there are line breaks or word wraps.
int[] tmpSize = new int[] {0, 0, 0, 0};
getSizeForWidth(tmpSize, width, str, font, offset);
return tmpSize[WIDTH];
| public static int[] | initGNL(javax.microedition.lcdui.Font font, int w, int h, int options, int offset)Sets up a new inout structure used in various
text methods.
int[] inout = new int[GNL_NUM_PARAMS];
inout[GNL_FONT_HEIGHT] = font.getHeight();
inout[GNL_WIDTH] = w;
inout[GNL_HEIGHT] = h;
inout[GNL_OPTIONS] = options;
inout[GNL_OFFSET] = offset;
inout[GNL_ELLIP_WIDTH] = font.charWidth(truncationMark);
inout[GNL_LINE_START] = 0;
inout[GNL_LINE_END] = 0;
inout[GNL_NEW_LINE_START] = 0;
inout[GNL_LINE_WIDTH] = 0;
inout[GNL_NUM_LINES] = 0;
return inout;
| public static int | paint(javax.microedition.lcdui.Graphics g, java.lang.String str, javax.microedition.lcdui.Font font, int fgColor, int fgHColor, int w, int h, int offset, int options, TextCursor cursor)Paints the text, linewrapping when necessary.
if (w <= 0 ||
(cursor == null && (str == null || str.length() == 0))) {
return 0;
}
if (str == null) {
str = "";
}
g.setFont(font);
g.setColor(fgColor);
char[] text = str.toCharArray();
int fontHeight = font.getHeight();
if (cursor != null && cursor.visible == false) {
cursor = null;
}
int[] inout = initGNL(font, w, h, options, offset);
int numLines = 0;
int height = 0;
do {
numLines++;
height += fontHeight;
if (height > h) {
break;
}
inout[GNL_NUM_LINES] = numLines;
boolean truncate = getNextLine(text, font, inout);
int lineStart = inout[GNL_LINE_START];
int lineEnd = inout[GNL_LINE_END];
int newLineStart = inout[GNL_NEW_LINE_START];
//
// now we can get around to actually draw the text
// lineStart is the array index of the first character to
// start drawing, while lineEnd is the index just after
// the last character to draw.
//
if (lineEnd > lineStart) {
if ((options & INVERT) == INVERT) {
g.setColor(fgHColor);
} else {
g.setColor(fgColor);
}
if ((options & HYPERLINK) == HYPERLINK) {
drawHyperLink(g, offset, height, inout[GNL_LINE_WIDTH]);
}
//
// we are given x,y coordinates and we must calculate
// the best array index to put the cursor
//
if (cursor != null &&
cursor.option == PAINT_GET_CURSOR_INDEX &&
cursor.x >= 0 &&
cursor.y == height) {
int bestIndex = lineStart;
int bestX = offset;
int curX = offset;
int curY = height;
//
// draw one character at a time and check its position
// against the supplied coordinates in cursor
//
for (int i = lineStart; i < lineEnd; i++) {
char ch = text[i];
g.drawChar(ch, curX, curY,
Graphics.BOTTOM | Graphics.LEFT);
if (Math.abs(curX - cursor.preferredX) <
Math.abs(bestX - cursor.preferredX)) {
bestIndex = i;
bestX = curX;
}
curX += font.charWidth(ch);
}
if (Math.abs(curX - cursor.preferredX) <
Math.abs(bestX - cursor.preferredX)) {
bestIndex = lineEnd;
bestX = curX;
}
//
// draw the ellipsis
//
if (truncate) {
g.drawChar(truncationMark,
curX, curY,
Graphics.BOTTOM | Graphics.LEFT);
}
cursor.index = bestIndex;
cursor.x = bestX;
cursor.y = height;
cursor.option = PAINT_USE_CURSOR_INDEX;
} else {
g.drawChars(text, lineStart, lineEnd - lineStart,
offset, height,
Graphics.BOTTOM | Graphics.LEFT);
//
// draw the ellipsis
//
if (truncate) {
g.drawChar(truncationMark,
offset + font.charsWidth(
text, lineStart, lineEnd),
height,
Graphics.BOTTOM | Graphics.LEFT);
}
}
}
//
// try to draw a vertical cursor indicator
//
if (cursor != null &&
cursor.option == PAINT_USE_CURSOR_INDEX &&
cursor.index >= lineStart && cursor.index <= lineEnd) {
int off = offset;
if (cursor.index > lineStart) {
off += font.charsWidth(text, lineStart,
cursor.index - lineStart);
}
cursor.x = off;
cursor.y = height;
cursor.width = 1;
cursor.height = fontHeight;
cursor.paint(g);
cursor = null;
}
inout[GNL_LINE_START] = newLineStart;
inout[GNL_OFFSET] = 0;
offset = 0;
} while (inout[GNL_LINE_END] < text.length);
return inout[GNL_LINE_WIDTH];
| public static int | paintLine(javax.microedition.lcdui.Graphics g, java.lang.String str, javax.microedition.lcdui.Font font, int fgColor, int w, int h, TextCursor cursor, int offset)Paints the text in a single line, scrolling left or right as
necessary to keep the cursor visible within the available
width for the text. The offset of the text after the
paintLine call, whether modified or not, is returned.
If the cursor is null, signifying an uneditable TextField is
being painted, the text will not be scrolled left or right, and
the returned value will always equal the offset
argument passed in to this method.
if (w <= 0 ||
(cursor == null && (str == null || str.length() == 0))) {
return 0;
}
if (str == null) {
str = "";
}
g.setFont(font);
g.setColor(fgColor);
char[] text = str.toCharArray();
int fontHeight = font.getHeight();
if (cursor != null && cursor.visible == false) {
cursor = null;
}
// side-scroll distance in pixels, with default
int scrollPix = w / 2;
//
// draw a vertical cursor indicator if required
//
if (cursor != null &&
cursor.option == PAINT_USE_CURSOR_INDEX &&
cursor.index >= 0 && cursor.index <= str.length()) {
int pos = offset;
if (cursor.index > 0) {
pos += font.charsWidth(text, 0, cursor.index);
}
// IMPL_NOTE: optimize this with math instead of iteration
cursor.x = pos;
if (cursor.x >= w) {
while (cursor.x >= w) {
offset -= scrollPix;
cursor.x -= scrollPix;
}
} else {
while ((cursor.x < w / 2) && (offset < 0)) {
offset += scrollPix;
cursor.x += scrollPix;
}
}
cursor.y = fontHeight;
cursor.width = 1;
cursor.height = fontHeight;
cursor.paint(g);
cursor = null;
}
g.drawChars(text, 0, text.length, offset, h,
Graphics.BOTTOM | Graphics.LEFT);
return offset;
| public static void | paintText(TextInfo info, javax.microedition.lcdui.Graphics g, java.lang.String str, javax.microedition.lcdui.Font font, int fgColor, int fgHColor, int w, int h, int offset, int options, TextCursor cursor)Paints text from a TextInfo structure.
// NOTE paint not called if TextInfo struct fails
g.setFont(font);
g.setColor(fgColor);
char[] text = str.toCharArray();
int fontHeight = font.getHeight();
if (cursor != null && cursor.visible == false) {
cursor = null;
}
int currentLine = info.topVis;
int height = currentLine * fontHeight;
int y = 0;
while (currentLine < (info.topVis + info.visLines)) {
height += fontHeight;
y += fontHeight;
g.drawChars(text, info.lineStart[currentLine],
info.lineEnd[currentLine] - info.lineStart[currentLine],
offset, y,
Graphics.BOTTOM | Graphics.LEFT);
// draw the vertical cursor indicator if needed
// update the cursor.x and cursor.y info
if (cursor != null &&
cursor.option == PAINT_USE_CURSOR_INDEX &&
cursor.index >= info.lineStart[currentLine] &&
cursor.index <= info.lineEnd[currentLine]) {
int off = offset;
if (cursor.index > info.lineStart[currentLine]) {
off += font.charsWidth(text, info.lineStart[currentLine],
cursor.index -
info.lineStart[currentLine]);
}
cursor.x = off;
cursor.y = height;
cursor.width = 1; // IMPL_NOTE: must these always be set?
cursor.height = fontHeight;
cursor.paint(g);
cursor = null;
}
offset = 0;
currentLine++;
}
| public static boolean | updateTextInfo(java.lang.String str, javax.microedition.lcdui.Font font, int w, int h, int offset, int options, TextCursor cursor, TextInfo info)Creates a current TextInfo struct, linewraping text
when necessary. TextInfo struct is updated when
str changes, or when scrolling happens.
This method does not do any painting, but updates
info to be current for use by the
paint routine, paintText ...
if (w <= 0 ||
(cursor == null && (str == null || str.length() == 0))) {
return false;
}
if (str == null) {
str = "";
}
char[] text = str.toCharArray();
int fontHeight = font.getHeight();
if (cursor != null && cursor.visible == false) {
cursor = null;
}
if (info.isModified) {
int[] inout = initGNL(font, w, h, options, offset);
int numLines = 0;
int height = 0;
do {
numLines++;
height += fontHeight;
info.numLines = numLines;
if (height < h) {
info.visLines = info.numLines;
}
inout[GNL_NUM_LINES] = numLines;
getNextLine(text, font, inout);
int lineStart = inout[GNL_LINE_START];
int lineEnd = inout[GNL_LINE_END];
int newLineStart = inout[GNL_NEW_LINE_START];
// IMPL_NOTE: add accessor fn to TextInfo and hide this
//
// check that we don't exceed info's capacity
// before we cache line data and expand if needed
//
if (numLines > info.lineStart.length) {
info.expand();
}
info.lineStart[numLines - 1] = lineStart;
info.lineEnd[numLines - 1] = lineEnd;
inout[GNL_LINE_START] = newLineStart;
inout[GNL_OFFSET] = 0;
offset = 0;
} while (inout[GNL_LINE_END] < text.length);
info.height = height;
}
if (info.scrollY) {
// if (lineEnd > lineStart) {
// we are given x,y coordinates and we must calculate
// the best array index to put the cursor
//
if (cursor != null &&
cursor.option == PAINT_GET_CURSOR_INDEX &&
cursor.x >= 0) {
// cursor.y == height) {
int curLine = (cursor.y / fontHeight) - 1;
int curX = curLine == 0 ? offset : 0;
int curY = cursor.y;
int bestX = curX;
int bestIndex = info.lineStart[curLine];
// take one character at a time and check its position
// against the supplied coordinates in cursor
//
int lineStart = info.lineStart[curLine];
int lineEnd = info.lineEnd[curLine];
for (int i = lineStart; i < lineEnd; i++) {
char ch = text[i];
if (Math.abs(curX - cursor.preferredX) <
Math.abs(bestX - cursor.preferredX)) {
bestIndex = i;
bestX = curX;
}
curX += font.charWidth(ch);
}
if (Math.abs(curX - cursor.preferredX) <
Math.abs(bestX - cursor.preferredX)) {
bestIndex = lineEnd;
bestX = curX;
}
cursor.index = bestIndex;
cursor.x = bestX;
// cursor.y = height;
cursor.option = PAINT_USE_CURSOR_INDEX;
info.cursorLine = curLine;
}
}
if (info.scrollX || info.isModified) {
if (cursor != null &&
cursor.option == PAINT_USE_CURSOR_INDEX) {
if (cursor.index >= info.lineStart[info.cursorLine] &&
cursor.index <= info.lineEnd[info.cursorLine]) {
// no change to info.cursorLine
} else {
// IMPL_NOTE: start at cursorLine and search before/after
// as this search is non-optimal
for (int i = 0; i < info.numLines; i++) {
// we are given an index...what line is it on?
if (cursor.index >= info.lineStart[i] &&
cursor.index <= info.lineEnd[i]) {
info.cursorLine = i;
break;
}
}
}
}
}
// check scroll position and move if needed
if (cursor != null && (info.isModified ||info.scrollX || info.scrollY)) {
if (info.numLines > info.visLines) {
if (info.cursorLine > info.topVis + info.visLines - 1) {
int diff = info.cursorLine -
(info.topVis + info.visLines - 1);
info.topVis += diff;
} else if (info.cursorLine < info.topVis) {
int diff = info.topVis - info.cursorLine;
info.topVis -= diff;
}
if (info.topVis + info.visLines > info.numLines) {
info.topVis = info.numLines - info.visLines;
}
} else {
info.topVis = 0;
}
cursor.yOffset = info.topVis * fontHeight;
}
info.scrollX = info.scrollY = info.isModified = false;
return true;
|
|