Summary: The classes on this page provide the convenient methods for handling the
java.text.AttributedString and java.text.AttributedCharacterIterator.
|
Relevant major classes of Java SE: java.awt.event.MouseListener, MouseMotionListener, MouseEvent
|
Classes on this page: LineBreaker,
Line, StringTokenizerEx, CaretPosition
|
1. Class LineBreaker
return=>page top
1.1 Overview
The attributed string (styled text) is broken into multiple lines which
it the rectafngle area by the java.awt.font.LineBreakMeasurer.
The LineBreakMeasurer doesn't break the attributed string at "\n" (line feed),
so we prepare some special methods for handling "\n" (line feed).
The multiple lines are represented by the array of java.awt.font.TextLayout objects (TextLayout[] textLayouts)
and the positions of the TextLayout objects are stored in the array of Point2D objects
(Point2D[] textLayoutPositions).
The textLayoutPositions[n] represents the left lower position of the corresponding TextLayout object
(Figure 1.1 (a)), exactly it's the left position on the baseline (Figure 1.1 (b)).
:
Text index, line index and column index.
Each index is represented by the following variable:
◦ textIndex - text index。
◦ lineindex - line index which is determined by the Linebreaker.
◦ columnIndex - local text index in the specified line which is determined by the Linebreaker.
: Line feed("\n")
A line feed is inserted by pressing enter key. The line feeds are placed such as the above figure.
They aren't displayed on the canvas.
(a)TextLayout objects
|
(b) The parameters of TextLayout
|
Figure 1.1 LineBreaker
1.2 API
public class LineBreaker
Field
|
Description
|
textIterator
|
private AttributedCharacterIterator textIterator
The text to be displayed.
|
textBox |
private TextBox textBox
The TextBox object which uses this LineBreaker object. |
textArea
|
private Rectangle2D textArea
The rectangle area in which the text is displayed.
|
textAlign
|
private int textAlign
The text align. Left align: 0. Center Align; 1, Right align: 2.
|
lineSpace
|
private int lineSpace
The line space.
|
lineList
|
private ArrayList lineList
The ArrayList which stores Line objects.
|
widthLimit
|
private int widthLimit=5
If the width of the textArea is 0,
then the text wrapping width is given by this value.
|
Method
|
Description
|
Constructor |
public LineBreaker(){} |
setData
|
public void setData(AttributedCharacterIterator textIterator, textBox textBox)
◦ Sets the textBox to the corresponding fields.
Gets values from the TextBox object and sets them to the textArea, textAlign
and lineSpace fields.
◦ If the textIterator parameter isn't null,
then calls the createMultipleLines method.
|
createMultipleLines
|
private void createMultipleLines()
∙ Calls the createLineBreakPositions method.
Returns the line break positions (int[] breakPositions).
∙ Creates new TextLayout objects corresponding the multiple lines based
on the line break positions and save them to the array (TextLayout[] textLayouts).
Gets the attributed string by the
AttributedStringUtil.getTextLayoutString method.
: "\n" (Line feed) stored in a TextLayout object
The characters in a TextLayout are displayed on the DrawPanel by the TextLayout.draw method in the TextBox.drawText method. However, the "\n" in the TextLayout isn't display at
all and "\n" can't be selected by the TextLayout.hitTestChar
method in the TextBox.setCaretPositionOrSelection.
For this reason, "\n" is replaced with " "(space) or
in AttributedStringUtil.getTextLayoutString method
and displayed on the DrawPanel.
∙ Calls the createTextLayoutPositions method
and saves the left lower positions of the TextLayout objects to
the array (Point2D[] textLayoutPositions).
Point2D[] textLayoutPositions=createTextLayoutPositions(textLayouts);
∙ Creates new Line objects having all information of the lines
and save the objects to the
lineList.
Line line=new Line(breakPositions[i], breakPositions[i+1], textLayoutPositions[i],
textLayouts[i], layoutStrings[i]);
|
createLineBreakPositions
|
private int[] createLineBreakPositions(AttributedCharacterIterator textIterator,
float formatWidth)
Parameters:
textIterator - Same as the textIterator field.
formatWidth - The width of rectangle area in which the text is displayed.
Returns:
The line break positions.
Processing:
∙ Gets the string from the textIterator
by the AttributedStringUtil.getString method
and creates the StringTokenizerEx object
with the string to break the string at "\n" (line feed)
∙ Gets the sub string which was broken at "\n" by the
nextToken of the
StringTokenizerEx and creates
the java.awt.font.LineBreakMeasurer object.
The break positions can be got by the nextOffset method of the LineBreakMeasurer.
|
createTextLayoutPositions
|
private Point2D[] createTextLayoutPositions(TextLayout[] layout)
Allocates the positions of the TextLayout objects (TextLayout[] textLayouts)
from the left upper position of the textArea. To determine the positions, the getAscent, getAdvance and getDescent
methods of the TextLayout are used.
|
createTextLayoutBounds
|
private Rectangle2D[] createTextLayoutBounds(TextLayout[] layout, Point2D[]
textLayoutPositions)
Returns the array of the Rectangle2D objects, each of which encloses the
corresponding TextLayout object.
|
getString
|
public String getString(CharacterIterator iterator, int begin, int end)
Returns the string of the [start, end] range of the
textIterator.
|
getTextLayouts
|
public TextLayout[] getTextLayouts()
Returns the array of the TextLayout objects. If there is no TextLayout
object, return the array of 0-length.
|
getTextLayout
|
public TextLayout getTextLayout(int lineIndex)
Returns the TextLayout object specified by the lineIndex.
|
getTextLayoutStrings
|
public String[] getTextLayoutStrings()
Returns the array of the strings which are stored in the TextLayout objects.
To get the string, the Line.getTextLayoutString method is used.
|
getTextLayoutString
|
public String getTextLayoutString(int lineIndex)
Parameter:
lineIndex - The line index (lineIndex=0,1, 2,....)
Returns:
Returns the string which is stored in the TextLayout object specified by
the lineIndex).
To get the string, the Line.getTextLayoutString method is used.
|
getPreceedingString
|
private String getPreceedingString(int lineIndex, int columnIndex)
Parameter:
lineIndex - The line index (lineIndex=0,1, 2,....)
columnIndex - The character index in the lineIndex-th TextLayout object (textLayouts[lineIndex])
Returns:
The sub-string of the textIterator
from top to the columnIndex-th character of the lineIndex-th TextLayout object (textLayouts[lineIndex]).
|
getPreceedingCharacter
|
private String getPreceedingCharacter(int lineIndex, int columnIndex)
Parameter:
lineIndex - The line index (lineIndex=0,1, 2,....)
columnIndex - The character index in the lineIndex-th TextLayout object (textLayouts[lineIndex])
Returns:
The character of the textIterator at (lineIndex, columnIndex).
(lineIndex, columnIndex) =>
Usage of the CaretPosition
|
getTextLayoutPositions
|
public Point2D[] getTextLayoutPositions()
Returns the array of the positions of the TextLayout objects.
The position of the TextLayout object represents the left lower position
of the TextLayout object (Figure 5.1
(a) textLayoutPositions[n]), exactly it's the left position on the baseline
(Figure 5.1 (b)).
|
getBounds
|
public Rectangle2D[] getBounds()
Returns the array the rectangles, each of which encloses the TextLayout object.
|
getBounds
|
public Rectangle2D getBounds(int index)
returns the rectangle which encloses the index-th TextLayout object.
|
getCharacterCount
|
public int getCharacterCount()
Retruns the number of the characters of the textIterator.
|
getCharacterCount
|
public int getCharacterCount(int lineIndex)
Returns the number of the characters of the lineIndex-th line.
|
getCharacterCount
|
public int getCharacterCount(int lineIndex, int columnIndex)
Returns the number of the characters of the
textIterator from the top to (lineIndex, columnIndex.
(lineIndex, columnIndex) =>
Fig 5.1
|
getLineColumnIndices |
public int[] getLineColumnIndices(int textIndex)
Returns the line index and the column index which are converted from the
text index (textIndex).
The returned int array indices stores the line index at indices[0] and
the column index at indices[1]. |
getTextIndex |
public int getTextIndex(int lineIndex, int columnIndex)
Returns the text index which is converted from the line index (lineIndex)
and the column index (columnIndex).
(lineIndex, columnIndex) =>
Fig 5.1 |
updateCaretPosition
|
public CaretPosition updateCaretPosition(int textIndex)
Deprecated. Uses CaretPosition.updateCaretPosition.
Parameter:
textIndex - the text index.
Returns:
The CaretPosition object.
Processing:
This method can be performed easily by using the above
getLineColumnIndices method.
|
getOffsetCaretPosition
|
public CaretPosition getOffsetCaretPosition(CaretPosition caretPosition,
int offset)
Deprecated. Uses
CaretPosition.columnOffset.
Parameter:
caretPosition - The CaretPosition object representing the current text cursor (caret) position.
offset - The offset value for the new cursor (caret) position. Minus offset is available.
Returns:
The CaretPosition object which represents the offset text cursor (caret)
position from the current text cursor (caret) position.
Processing:
The method is called by the keyPressed method of
the TextBox to move the text cursor (caret) to leftward or rightward.
|
getOffsetCaretPosition
|
private CaretPosition getOffsetCaretPosition(int lineIndex, int columnIndex, int offset)
Deprecated. Uses
CaretPosition.offsetCaretPosition.
Parameter:
lineIndex - The line index (lineIndex=0,1, 2,....)
columnIndex - The character index in the lineIndex-th TextLayout object (textLayouts[lineIndex])
(columnIndex=1, 2,....)
offset - The offset value for the new cursor (caret) position. Minus offset is available.
Returns:
The CaretPosition object which represents the offset text cursor (caret)
position from the position of the (lineIndex, columnIndex).
Processing:
Returns the returned value of the updateCaretPosition.
|
getLineOffsetCaret
Position
|
public CaretPosition getLineOffsetCaretPosition(CaretPosition caretPosition,
int lineOffset)
Deprecated.
Uses CaretPosition.lineOffset.
Parameter:
caretPosition - The CaretPosition object representing the current text cursor (caret) position.
lineOffset - The line offset value for the new cursor (caret) position. Minus offset is available.
Returns:
The CaretPosition object which represents the offset text cursor (caret)
position by line from the current text cursor (caret) position.
Processing:
The method is called by the keyPressed method of
the TextBox to move the text cursor (caret) to upper or lower.
|
getCaretRectangle
|
public Rectangle getCaretRectangle(CaretPosition caretPosition, int offset)
Parameter:
caretPosition - The CaretPosition object representing the current text cursor (caret) position.
offset - The offset value for the new cursor (caret) position. Minus offset is available.
Returns:
The Rectangle object which represents the shape of the offset text cursor(caret).
Processing:
The method is called by the getTextLocation
and drawCaret methods of the TextBox.
The offset value is used when the composed text exists and
the text cursor (caret) should be drawn after the composed text.
(a) If the textIterator equals null, then performs the following.
This case happens when the textBox has no text.
That is when the textBox was newly created or when the text in the textBox was completely deleted
(Case (a)).
In this case the attributed string(Java Class AttributedString) doesn't exist
in the textArea of the textBox,
especially the appropriate height of the caret rectangle is unknown.
So this method creates a temporal TextLayout object storing also the temporal attributed string of a space character
and determine the height of the caret rectangle by the ascent and descent
(Figure 1.1 (b)) of the temporal TextLayout.
As the result, the left upper position of the textArea
is assigned to position of the caret rectangle, the (ascent + descent) to
the height of caret rectangle and 0 to its width.
(b) If the parameter: caretPosition points inside a existing line, then performs the following.
This case happens when at least one of the composed text
and committed text is being displayed (Case (b)).
This method gets the caret shape by the getCaretShapes method of the TextLayout as follow.
Shape[] carets=textLayout.getCaretShapes(index);
And creates the caret rectangle by using the return value: carets[0].
(c)If the parameter: caretPosition points the end of a line, then performs the following.
In this case, this method displays the caret at the beginning of the next line
(Case (c)).
This method gets the caret rectangle in the same way as in (b), and changes its position to the beginning of the next line.
This processing can be calculated from ascent, descent
and lineSpace values.
|
|
|
Case (a) |
Case (b) |
Case (c) |
Figure Caret rectangle (red mark) |
|
printTextLayoutPositions
|
public void printTextLayoutPositions()
Prints the positions of the TextLayout objects for debug.
|
printTextLayouts
|
public void printTextLayouts()
Prints the number of characters, the characters and so on of the TextLayout
objects for debug.
|
printBounds
|
public void printBounds()
Prints the bounds of the TextLayout objects for debug.
|
rangeCheck |
private void rangeCheck(int index, int indexMax) throws RangeException
If index>indexMax, this method throws the RangeException.
The purpose of this simple method is to call e.printStackTrace() when an
error is detected. |
textRangeError |
private boolean textRangeError(int lineIndex, String errMessage)
If textIndex>(the number of the characters in the textIterator), this method outputs the error message and the StackTrace. |
lineRangeError |
private boolean lineRangeError(int lineIndex, String errMessage)
If lineIndex>this.lineList.size(), this method outputs the error message
and the StackTrace. |
lineColumnRangeError |
private boolean lineColumnRangeError(int lineIndex, int columnIndex, String
errMessage)
If lineIndex>this.lineList.size() or columnIndex>columMax, this method
outputs the error message and the StackTrace. |
1.3 RangeException - Inner class of LineBreaker
code
|
class RangeException extends Exception {
RangeException() {}
public String toString() {
return "range Exception";
}
}
|
2. Class Line
return=>page top
public class Line
This class represents the text line created by the LineBreaker.
Field
|
Description
|
startCharPosition
|
int startCharPosition
The text cursor (caret) position at the start of this line in the committed text.
|
endCharPosition
|
int endCharPosition
The text cursor (caret) position at the end of this line in the committed text.
|
textLayoutPosition
|
Point2D textLayoutPosition
The left edge point of the TextLayout object.
|
textLayout
|
TextLayout textLayout
The TextLayout object of this line.
|
textLayoutString
|
String textLayoutString
The text string of this line.
|
Method
|
Description
|
Constructor
|
public Line(int startCharPosition, int endCharPosition, Point2D textLayoutPosition,
TextLayout textLayout, String textLayoutString)
Sets the parameters to the corresponding fields.
|
getStartCharPosition
|
public int getStartCharPosition()
Returns the startCharPosition field.
|
getEndCharPosition
|
public int getEndCharPosition()
Returns the endCharPosition field.
|
getTextLayoutPosition
|
public Point2D getTextLayoutPosition()
Returns the textLayoutPosition field.
|
getTextLayout
|
public TextLayout getTextLayout()
Returns the textLayout field.
|
getTextLayoutString
|
public String getTextLayoutString()
Returns the ttextLayoutString field.
|
3. Class StringTokenizerEx
return=>page top
public class StringTokenizerEx
The class performs the similar functions as the java.util.StringTokenizer.
This class provides the methods which can break attributed text into lines
at "\n"(line feed), if the "\n"(line feed) is specified
as a delimiter. This class is used by the LineBreaker.
Field
|
Description
|
str
|
String str:The text to be broken into lines.
|
delim
|
String delim:The delimiter string.
|
index
|
int index:The index in the text.
|
Method
|
Description
|
Constructor
|
public StringTokenizerEx(String str, String delim)
Sets the parameters to the corresponding fields.
|
hasMoreTokens
|
public boolean hasMoreTokens()
Tests if there are more tokens available from the str.
|
nextToken
|
public String nextToken()
Returns the next token.
|
4. Class CaretPosition
return=>page top
4.1 Usage of the CaretPosition
(1) The text cursor (caret) position
The text cursor (caret) position can be represented by the following two forms.
(a) Using the text index (one dimensional representation)
Let's denote the text index as textIndex (textIndex=0,1,...). The cursor
position is denoted as textIndex before the textIndex-th character and denoted as textIndex+1
behind the textIndex-th character.
(b) Using the line index and the position in the line (two dimensional
representation)
Let's denote the line index as lineIndex (lineIndex=0,1,2...,n) and the
position in the line (local text index) as columnIndex
The two dimensional indexing of (lineIndex, columnIndex) determines the
text cursor (caret) position.
(2) The conversion between textIndex
and (lineIndex, columnIndex).
The (lineIndex, columnIndex) and the textIndex are one-to-one correspondence
except the start position or the end position of the line, therefore they
can generally be converted each other. It is necessary for this conversion
to refer the array of the TextLayout objects given by the LineBreaker.
∙ (lineIndex, columnIndex)=> textIndex
Uses the LineBreaker.getTextIndext method.
∙ textIndex => (lineIndex, columnIndex)
Uses the LineBreaker.getLineColumnIndices method.
4.2 API
Hereafter, we represent the indexes of (i, j) and k as the variables of
(lineIndex, index) and textIndex.
public class CaretPosition
Field |
Description |
lineIndex
|
int lineIndex=-1
The number of the TexyLayout object which corresponds the line number and
on which the text cursor exists. The number of -1 means that no TexyLayout object exists.
|
columnIndex
|
int columnIndex=-1
The text cursor position in the lineIndex-thTexyLayout object.
|
textIndex
|
int textIndex=-1
The text cursor position in the text to be displayed.
|
lineFeedOption |
boolean lineFeedOption
If lineFeedOption==true and the text cursor (caret) position is located
just behind a \n (line feed), then the cursor's position is automatically
changed to the top position of the next line.
String str="";
if(lineFeedOption&&columnIndex>0){
str=lineBreaker.getPreceedingCharacter(lineIndex, columnIndex);
if(str.equals("\n")){
lineIndex++;
columnIndex=0;
}
}
: lineFeedOption
If the CaretPosition object is used for an ordinary word prosessor,
sets true to the lineFeedOption.
If the two CaretPosition objects is used to show the bound of
a selected text, sets false to the lineFeedOption. In this case,
the first CaretPosition object specifies the position just before the top
character of the selected text and the second object specifies the position
just behind the last character of the selected text,
=>
TextBox.selStart,
TextBox.selEnd
|
Method
|
Description
|
Constructor
|
public CaretPosition(int lineIndex, int columnIndex)
The constructor is used to create a trivial CaretPosition object such as
new CaretPosition(-1, -1), new CaretPosition(0, 0) or so on.
To create an object in which the textindex is consistent with the lineIndex
and the lineColumnIndex, uses the CaretPosition.getCaretPosition static method.
|
Constructor
|
public CaretPosition(int lineIndex, int columnIndex, boolean lineFeedOption)
|
Constructor
|
public CaretPosition(int lineIndex, int columnIndex, int textIndex)
|
Constructor
|
public CaretPosition(int lineIndex, int columnIndex, int textIndex, boolean lineFeedOption)
|
isValid |
public boolean isValid()
Returns true if lineindex>=0, columnIndex>=0 and textIndex>=0. |
getLineIndex
|
public int getLineIndex()
Returns the lineIndex.
|
getColumnIndex
|
public int getColumnIndex()
Returns the positionInLine.
|
getTextIndex
|
public int getTextIndex()
Returns the textIndex.
|
resetPosition |
public void resetPosition()
Sets 0 to all the field variablres. |
updateCaretPosition |
public void updateCaretPosition(int newTextIndex, LineBreaker lineBreaker,
String callFrom)
Parameter:
newTextIndex - The text index.
lineBreaker - The LineBreaker object.
callFrom - This is used for debug.
Returns:
The CaretPosition object.
Processing:
This method updates the field variables of the lineIndex and
columIndex for the given newTextIndex.
This method calls the LineBreaker,.getLineColumnIndices method.
|
columnOffset |
public void columnOffset(int offset, LineBreaker lineBreaker)
Parameter:
offset - the horizontal offset value. Minus offset is available.
lineBreaker - the LineBreaker object.
Processing:
The method is called by the TextBox.keyPressed method of the TextBox to move the text cursor (caret) to leftward or rightward.
This method is performed by calling the offsetCaretposition method.
|
offsetCaretPosition |
private void offsetCaretPosition(int lineIndex, int columnIndex, int offset, LineBreaker lineBreaker)
Parameter:
lineIndex - The line index.
columIndex - The column index.
offset - The horizontal offset value
lineBreaker - The LineBreaker object.
=>
Figure 5.1, 5.1 The usage of the CaretPosition
Processing:
This method is called from the columnOffset method mentioned above and
the lineOffset method mentioned below. This method counts the number of
characters from the top of the text to the position specified by the
(lineIndex, columIndex) and gets the new textIndex (field variable)
by adding the offset to the number of characters, and finally updates this object by calling the
updateCaretPosition method.
|
lineOffset |
public void lineOffset(int lineOffset, LineBreaker lineBreaker)
Parameter:
lineOffset - the vertical offset value. Minus offset is available.
lineBreaker - LineBreaker object.
Processing:
The method is called by the TextBox.keyPressed method
of the TextBox to move the text cursor (caret) to upper or lower.
This method is performed by calling the offsetCaretposition method.
|
print
|
public void print(String message)
Prints the caret position with the message for debug.
|
toString
|
public String toString()
Return the string representing this object.
|
getCaretPosition (static) |
public static CaretPosition getCaretPosition(int textIndex, boolean lineFeedOption,
LineBreaker lineBreaker, String callFrom)
Parameter:
textIndex - The text index.
lineFeedOption - line feed option(see=> field variable lineFeedOption)
lineBreaker - The LineBreaker object.
callFrom - The class name and method name calling this method (for debug)
Returns:
CaretPosition - The CaretPosition object.
Processing:
This method calculates the (lineIndex, columIndex) from the textIndex
by the LineBreaker.getLineColumnIndices method
and creates the new CaretPosition object.
|
getCaretPosition (static) |
public static CaretPosition getCaretPosition(int lineIndex, int columnIndex,
boolean lineFeedOption, LineBreaker lineBreaker, String callFrom)
Parameter:
lineIndex - The line index.
columIndex - The column index.
lineFeedOption - line feed option(=> field variablelineFeedOption)
lineBreaker - The LineBreaker object.
callFrom - The class name and method name calling this method (for debug)
=>
Figure 5.1, 5.1 The usage of the CaretPosition
Returns:
CaretPosition - The CaretPosition object.
Processing:
This method calculates the textIndex from the (lineIndex, columIndex) by the
LineBreaker.getTextIndex method
and creates the new CaretPosition object.
|
|