Utilitiespublic class Utilities extends Object A collection of methods to deal with various text
related activities. |
Methods Summary |
---|
static int | drawComposedText(javax.swing.text.View view, javax.swing.text.AttributeSet attr, java.awt.Graphics g, int x, int y, int p0, int p1)Draws the given composed text passed from an input method.
Graphics2D g2d = (Graphics2D)g;
AttributedString as = (AttributedString)attr.getAttribute(
StyleConstants.ComposedTextAttribute);
as.addAttribute(TextAttribute.FONT, g.getFont());
if (p0 >= p1)
return x;
AttributedCharacterIterator aci = as.getIterator(null, p0, p1);
return x + (int)SwingUtilities2.drawString(
getJComponent(view), g2d,aci,x,y);
| public static final int | drawTabbedText(javax.swing.text.Segment s, int x, int y, java.awt.Graphics g, javax.swing.text.TabExpander e, int startOffset)Draws the given text, expanding any tabs that are contained
using the given tab expansion technique. This particular
implementation renders in a 1.1 style coordinate system
where ints are used and 72dpi is assumed.
return drawTabbedText(null, s, x, y, g, e, startOffset);
| static final int | drawTabbedText(javax.swing.text.View view, javax.swing.text.Segment s, int x, int y, java.awt.Graphics g, javax.swing.text.TabExpander e, int startOffset)Draws the given text, expanding any tabs that are contained
using the given tab expansion technique. This particular
implementation renders in a 1.1 style coordinate system
where ints are used and 72dpi is assumed.
JComponent component = getJComponent(view);
FontMetrics metrics = SwingUtilities2.getFontMetrics(component, g);
int nextX = x;
char[] txt = s.array;
int txtOffset = s.offset;
int flushLen = 0;
int flushIndex = s.offset;
int n = s.offset + s.count;
for (int i = txtOffset; i < n; i++) {
if (txt[i] == '\t") {
if (flushLen > 0) {
nextX = SwingUtilities2.drawChars(component, g, txt,
flushIndex, flushLen, x, y);
flushLen = 0;
}
flushIndex = i + 1;
if (e != null) {
nextX = (int) e.nextTabStop((float) nextX, startOffset + i - txtOffset);
} else {
nextX += metrics.charWidth(' ");
}
x = nextX;
} else if ((txt[i] == '\n") || (txt[i] == '\r")) {
if (flushLen > 0) {
nextX = SwingUtilities2.drawChars(component, g, txt,
flushIndex, flushLen, x, y);
flushLen = 0;
}
flushIndex = i + 1;
x = nextX;
} else {
flushLen += 1;
}
}
if (flushLen > 0) {
nextX = SwingUtilities2.drawChars(component, g,txt, flushIndex,
flushLen, x, y);
}
return nextX;
| public static final int | getBreakLocation(javax.swing.text.Segment s, java.awt.FontMetrics metrics, int x0, int x, javax.swing.text.TabExpander e, int startOffset)Determine where to break the given text to fit
within the given span. This tries to find a word boundary.
char[] txt = s.array;
int txtOffset = s.offset;
int txtCount = s.count;
int index = Utilities.getTabbedTextOffset(s, metrics, x0, x,
e, startOffset, false);
if (index >= txtCount - 1) {
return txtCount;
}
for (int i = txtOffset + index; i >= txtOffset; i--) {
char ch = txt[i];
if (ch < 256) {
// break on whitespace
if (Character.isWhitespace(ch)) {
index = i - txtOffset + 1;
break;
}
} else {
// a multibyte char found; use BreakIterator to find line break
BreakIterator bit = BreakIterator.getLineInstance();
bit.setText(s);
int breakPos = bit.preceding(i + 1);
if (breakPos > txtOffset) {
index = breakPos - txtOffset;
}
break;
}
}
return index;
| static javax.swing.JComponent | getJComponent(javax.swing.text.View view)If view 's container is a JComponent it
is returned, after casting.
if (view != null) {
Component component = view.getContainer();
if (component instanceof JComponent) {
return (JComponent)component;
}
}
return null;
| static int | getNextVisualPositionFrom(javax.swing.text.View v, int pos, javax.swing.text.Position$Bias b, java.awt.Shape alloc, int direction, javax.swing.text.Position$Bias[] biasRet)Provides a way to determine the next visually represented model
location that one might place a caret. Some views may not be visible,
they might not be in the same order found in the model, or they just
might not allow access to some of the locations in the model.
This implementation assumes the views are layed out in a logical
manner. That is, that the view at index x + 1 is visually after
the View at index x, and that the View at index x - 1 is visually
before the View at x. There is support for reversing this behavior
only if the passed in View is an instance of
CompositeView . The CompositeView
must then override the flipEastAndWestAtEnds method.
if (v.getViewCount() == 0) {
// Nothing to do.
return pos;
}
boolean top = (direction == SwingConstants.NORTH ||
direction == SwingConstants.WEST);
int retValue;
if (pos == -1) {
// Start from the first View.
int childIndex = (top) ? v.getViewCount() - 1 : 0;
View child = v.getView(childIndex);
Shape childBounds = v.getChildAllocation(childIndex, alloc);
retValue = child.getNextVisualPositionFrom(pos, b, childBounds,
direction, biasRet);
if (retValue == -1 && !top && v.getViewCount() > 1) {
// Special case that should ONLY happen if first view
// isn't valid (can happen when end position is put at
// beginning of line.
child = v.getView(1);
childBounds = v.getChildAllocation(1, alloc);
retValue = child.getNextVisualPositionFrom(-1, biasRet[0],
childBounds,
direction, biasRet);
}
}
else {
int increment = (top) ? -1 : 1;
int childIndex;
if (b == Position.Bias.Backward && pos > 0) {
childIndex = v.getViewIndex(pos - 1, Position.Bias.Forward);
}
else {
childIndex = v.getViewIndex(pos, Position.Bias.Forward);
}
View child = v.getView(childIndex);
Shape childBounds = v.getChildAllocation(childIndex, alloc);
retValue = child.getNextVisualPositionFrom(pos, b, childBounds,
direction, biasRet);
if ((direction == SwingConstants.EAST ||
direction == SwingConstants.WEST) &&
(v instanceof CompositeView) &&
((CompositeView)v).flipEastAndWestAtEnds(pos, b)) {
increment *= -1;
}
childIndex += increment;
if (retValue == -1 && childIndex >= 0 &&
childIndex < v.getViewCount()) {
child = v.getView(childIndex);
childBounds = v.getChildAllocation(childIndex, alloc);
retValue = child.getNextVisualPositionFrom(
-1, b, childBounds, direction, biasRet);
// If there is a bias change, it is a fake position
// and we should skip it. This is usually the result
// of two elements side be side flowing the same way.
if (retValue == pos && biasRet[0] != b) {
return getNextVisualPositionFrom(v, pos, biasRet[0],
alloc, direction,
biasRet);
}
}
else if (retValue != -1 && biasRet[0] != b &&
((increment == 1 && child.getEndOffset() == retValue) ||
(increment == -1 &&
child.getStartOffset() == retValue)) &&
childIndex >= 0 && childIndex < v.getViewCount()) {
// Reached the end of a view, make sure the next view
// is a different direction.
child = v.getView(childIndex);
childBounds = v.getChildAllocation(childIndex, alloc);
Position.Bias originalBias = biasRet[0];
int nextPos = child.getNextVisualPositionFrom(
-1, b, childBounds, direction, biasRet);
if (biasRet[0] == b) {
retValue = nextPos;
}
else {
biasRet[0] = originalBias;
}
}
}
return retValue;
| public static final int | getNextWord(javax.swing.text.JTextComponent c, int offs)Determines the start of the next word for the given location.
Uses BreakIterator.getWordInstance() to actually get the words.
int nextWord;
Element line = getParagraphElement(c, offs);
for (nextWord = getNextWordInParagraph(c, line, offs, false);
nextWord == BreakIterator.DONE;
nextWord = getNextWordInParagraph(c, line, offs, true)) {
// didn't find in this line, try the next line
offs = line.getEndOffset();
line = getParagraphElement(c, offs);
}
return nextWord;
| static int | getNextWordInParagraph(javax.swing.text.JTextComponent c, javax.swing.text.Element line, int offs, boolean first)Finds the next word in the given elements text. The first
parameter allows searching multiple paragraphs where even
the first offset is desired.
Returns the offset of the next word, or BreakIterator.DONE
if there are no more words in the element.
if (line == null) {
throw new BadLocationException("No more words", offs);
}
Document doc = line.getDocument();
int lineStart = line.getStartOffset();
int lineEnd = Math.min(line.getEndOffset(), doc.getLength());
if ((offs >= lineEnd) || (offs < lineStart)) {
throw new BadLocationException("No more words", offs);
}
Segment seg = SegmentCache.getSharedSegment();
doc.getText(lineStart, lineEnd - lineStart, seg);
BreakIterator words = BreakIterator.getWordInstance(c.getLocale());
words.setText(seg);
if ((first && (words.first() == (seg.offset + offs - lineStart))) &&
(! Character.isWhitespace(seg.array[words.first()]))) {
return offs;
}
int wordPosition = words.following(seg.offset + offs - lineStart);
if ((wordPosition == BreakIterator.DONE) ||
(wordPosition >= seg.offset + seg.count)) {
// there are no more words on this line.
return BreakIterator.DONE;
}
// if we haven't shot past the end... check to
// see if the current boundary represents whitespace.
// if so, we need to try again
char ch = seg.array[wordPosition];
if (! Character.isWhitespace(ch)) {
return lineStart + wordPosition - seg.offset;
}
// it was whitespace, try again. The assumption
// is that it must be a word start if the last
// one had whitespace following it.
wordPosition = words.next();
if (wordPosition != BreakIterator.DONE) {
offs = lineStart + wordPosition - seg.offset;
if (offs != lineEnd) {
return offs;
}
}
SegmentCache.releaseSharedSegment(seg);
return BreakIterator.DONE;
| public static final javax.swing.text.Element | getParagraphElement(javax.swing.text.JTextComponent c, int offs)Determines the element to use for a paragraph/line.
Document doc = c.getDocument();
if (doc instanceof StyledDocument) {
return ((StyledDocument)doc).getParagraphElement(offs);
}
Element map = doc.getDefaultRootElement();
int index = map.getElementIndex(offs);
Element paragraph = map.getElement(index);
if ((offs >= paragraph.getStartOffset()) && (offs < paragraph.getEndOffset())) {
return paragraph;
}
return null;
| public static final int | getPositionAbove(javax.swing.text.JTextComponent c, int offs, int x)Determines the position in the model that is closest to the given
view location in the row above. The component given must have a
size to compute the result. If the component doesn't have a size
a value of -1 will be returned.
int lastOffs = getRowStart(c, offs) - 1;
if (lastOffs < 0) {
return -1;
}
int bestSpan = Integer.MAX_VALUE;
int y = 0;
Rectangle r = null;
if (lastOffs >= 0) {
r = c.modelToView(lastOffs);
y = r.y;
}
while ((r != null) && (y == r.y)) {
int span = Math.abs(r.x - x);
if (span < bestSpan) {
offs = lastOffs;
bestSpan = span;
}
lastOffs -= 1;
r = (lastOffs >= 0) ? c.modelToView(lastOffs) : null;
}
return offs;
| public static final int | getPositionBelow(javax.swing.text.JTextComponent c, int offs, int x)Determines the position in the model that is closest to the given
view location in the row below. The component given must have a
size to compute the result. If the component doesn't have a size
a value of -1 will be returned.
int lastOffs = getRowEnd(c, offs) + 1;
if (lastOffs <= 0) {
return -1;
}
int bestSpan = Integer.MAX_VALUE;
int n = c.getDocument().getLength();
int y = 0;
Rectangle r = null;
if (lastOffs <= n) {
r = c.modelToView(lastOffs);
y = r.y;
}
while ((r != null) && (y == r.y)) {
int span = Math.abs(x - r.x);
if (span < bestSpan) {
offs = lastOffs;
bestSpan = span;
}
lastOffs += 1;
r = (lastOffs <= n) ? c.modelToView(lastOffs) : null;
}
return offs;
| static int | getPrevWordInParagraph(javax.swing.text.JTextComponent c, javax.swing.text.Element line, int offs)Finds the previous word in the given elements text. The first
parameter allows searching multiple paragraphs where even
the first offset is desired.
Returns the offset of the next word, or BreakIterator.DONE
if there are no more words in the element.
if (line == null) {
throw new BadLocationException("No more words", offs);
}
Document doc = line.getDocument();
int lineStart = line.getStartOffset();
int lineEnd = line.getEndOffset();
if ((offs > lineEnd) || (offs < lineStart)) {
throw new BadLocationException("No more words", offs);
}
Segment seg = SegmentCache.getSharedSegment();
doc.getText(lineStart, lineEnd - lineStart, seg);
BreakIterator words = BreakIterator.getWordInstance(c.getLocale());
words.setText(seg);
if (words.following(seg.offset + offs - lineStart) == BreakIterator.DONE) {
words.last();
}
int wordPosition = words.previous();
if (wordPosition == (seg.offset + offs - lineStart)) {
wordPosition = words.previous();
}
if (wordPosition == BreakIterator.DONE) {
// there are no more words on this line.
return BreakIterator.DONE;
}
// if we haven't shot past the end... check to
// see if the current boundary represents whitespace.
// if so, we need to try again
char ch = seg.array[wordPosition];
if (! Character.isWhitespace(ch)) {
return lineStart + wordPosition - seg.offset;
}
// it was whitespace, try again. The assumption
// is that it must be a word start if the last
// one had whitespace following it.
wordPosition = words.previous();
if (wordPosition != BreakIterator.DONE) {
return lineStart + wordPosition - seg.offset;
}
SegmentCache.releaseSharedSegment(seg);
return BreakIterator.DONE;
| public static final int | getPreviousWord(javax.swing.text.JTextComponent c, int offs)Determine the start of the prev word for the given location.
Uses BreakIterator.getWordInstance() to actually get the words.
int prevWord;
Element line = getParagraphElement(c, offs);
for (prevWord = getPrevWordInParagraph(c, line, offs);
prevWord == BreakIterator.DONE;
prevWord = getPrevWordInParagraph(c, line, offs)) {
// didn't find in this line, try the prev line
offs = line.getStartOffset() - 1;
line = getParagraphElement(c, offs);
}
return prevWord;
| public static final int | getRowEnd(javax.swing.text.JTextComponent c, int offs)Determines the ending row model position of the row that contains
the specified model position. The component given must have a
size to compute the result. If the component doesn't have a size
a value of -1 will be returned.
Rectangle r = c.modelToView(offs);
if (r == null) {
return -1;
}
int n = c.getDocument().getLength();
int lastOffs = offs;
int y = r.y;
while ((r != null) && (y == r.y)) {
offs = lastOffs;
lastOffs += 1;
r = (lastOffs <= n) ? c.modelToView(lastOffs) : null;
}
return offs;
| public static final int | getRowStart(javax.swing.text.JTextComponent c, int offs)Determines the starting row model position of the row that contains
the specified model position. The component given must have a
size to compute the result. If the component doesn't have a size
a value of -1 will be returned.
Rectangle r = c.modelToView(offs);
if (r == null) {
return -1;
}
int lastOffs = offs;
int y = r.y;
while ((r != null) && (y == r.y)) {
offs = lastOffs;
lastOffs -= 1;
r = (lastOffs >= 0) ? c.modelToView(lastOffs) : null;
}
return offs;
| public static final int | getTabbedTextOffset(javax.swing.text.Segment s, java.awt.FontMetrics metrics, int x0, int x, javax.swing.text.TabExpander e, int startOffset)Determines the relative offset into the given text that
best represents the given span in the view coordinate
system. This is implemented in a 1.1 style coordinate
system where ints are used and 72dpi is assumed.
return getTabbedTextOffset(s, metrics, x0, x, e, startOffset, true);
| public static final int | getTabbedTextOffset(javax.swing.text.Segment s, java.awt.FontMetrics metrics, int x0, int x, javax.swing.text.TabExpander e, int startOffset, boolean round)
if (x0 >= x) {
// x before x0, return.
return 0;
}
int currX = x0;
int nextX = currX;
// s may be a shared segment, so it is copied prior to calling
// the tab expander
char[] txt = s.array;
int txtOffset = s.offset;
int txtCount = s.count;
int n = s.offset + s.count;
for (int i = s.offset; i < n; i++) {
if (txt[i] == '\t") {
if (e != null) {
nextX = (int) e.nextTabStop((float) nextX,
startOffset + i - txtOffset);
} else {
nextX += metrics.charWidth(' ");
}
} else {
nextX += metrics.charWidth(txt[i]);
}
if ((x >= currX) && (x < nextX)) {
// found the hit position... return the appropriate side
if ((round == false) || ((x - currX) < (nextX - x))) {
return i - txtOffset;
} else {
return i + 1 - txtOffset;
}
}
currX = nextX;
}
// didn't find, return end offset
return txtCount;
| public static final int | getTabbedTextWidth(javax.swing.text.Segment s, java.awt.FontMetrics metrics, int x, javax.swing.text.TabExpander e, int startOffset)Determines the width of the given segment of text taking tabs
into consideration. This is implemented in a 1.1 style coordinate
system where ints are used and 72dpi is assumed.
int nextX = x;
char[] txt = s.array;
int txtOffset = s.offset;
int n = s.offset + s.count;
int charCount = 0;
for (int i = txtOffset; i < n; i++) {
if (txt[i] == '\t") {
nextX += metrics.charsWidth(txt, i-charCount, charCount);
charCount = 0;
if (e != null) {
nextX = (int) e.nextTabStop((float) nextX,
startOffset + i - txtOffset);
} else {
nextX += metrics.charWidth(' ");
}
} else if(txt[i] == '\n") {
// Ignore newlines, they take up space and we shouldn't be
// counting them.
nextX += metrics.charsWidth(txt, i - charCount, charCount);
charCount = 0;
} else {
charCount++;
}
}
nextX += metrics.charsWidth(txt, n - charCount, charCount);
return nextX - x;
| public static final int | getWordEnd(javax.swing.text.JTextComponent c, int offs)Determines the end of a word for the given location.
Uses BreakIterator.getWordInstance() to actually get the words.
Document doc = c.getDocument();
Element line = getParagraphElement(c, offs);
if (line == null) {
throw new BadLocationException("No word at " + offs, offs);
}
int lineStart = line.getStartOffset();
int lineEnd = Math.min(line.getEndOffset(), doc.getLength());
Segment seg = SegmentCache.getSharedSegment();
doc.getText(lineStart, lineEnd - lineStart, seg);
if(seg.count > 0) {
BreakIterator words = BreakIterator.getWordInstance(c.getLocale());
words.setText(seg);
int wordPosition = offs - lineStart + seg.offset;
if(wordPosition >= words.last()) {
wordPosition = words.last() - 1;
}
offs = lineStart + words.following(wordPosition) - seg.offset;
}
SegmentCache.releaseSharedSegment(seg);
return offs;
| public static final int | getWordStart(javax.swing.text.JTextComponent c, int offs)Determines the start of a word for the given model location.
Uses BreakIterator.getWordInstance() to actually get the words.
Document doc = c.getDocument();
Element line = getParagraphElement(c, offs);
if (line == null) {
throw new BadLocationException("No word at " + offs, offs);
}
int lineStart = line.getStartOffset();
int lineEnd = Math.min(line.getEndOffset(), doc.getLength());
Segment seg = SegmentCache.getSharedSegment();
doc.getText(lineStart, lineEnd - lineStart, seg);
if(seg.count > 0) {
BreakIterator words = BreakIterator.getWordInstance(c.getLocale());
words.setText(seg);
int wordPosition = seg.offset + offs - lineStart;
if(wordPosition >= words.last()) {
wordPosition = words.last() - 1;
}
words.following(wordPosition);
offs = lineStart + words.previous() - seg.offset;
}
SegmentCache.releaseSharedSegment(seg);
return offs;
| static boolean | isComposedTextAttributeDefined(javax.swing.text.AttributeSet as)
return ((as != null) &&
(as.isDefined(StyleConstants.ComposedTextAttribute)));
| static boolean | isComposedTextElement(javax.swing.text.Document doc, int offset)
Element elem = doc.getDefaultRootElement();
while (!elem.isLeaf()) {
elem = elem.getElement(elem.getElementIndex(offset));
}
return isComposedTextElement(elem);
| static boolean | isComposedTextElement(javax.swing.text.Element elem)
AttributeSet as = elem.getAttributes();
return isComposedTextAttributeDefined(as);
| static boolean | isLeftToRight(java.awt.Component c)
return c.getComponentOrientation().isLeftToRight();
| static void | paintComposedText(java.awt.Graphics g, java.awt.Rectangle alloc, javax.swing.text.GlyphView v)Paints the composed text in a GlyphView
if (g instanceof Graphics2D) {
Graphics2D g2d = (Graphics2D) g;
int p0 = v.getStartOffset();
int p1 = v.getEndOffset();
AttributeSet attrSet = v.getElement().getAttributes();
AttributedString as =
(AttributedString)attrSet.getAttribute(StyleConstants.ComposedTextAttribute);
int start = v.getElement().getStartOffset();
int y = alloc.y + alloc.height - (int)v.getGlyphPainter().getDescent(v);
int x = alloc.x;
//Add text attributes
as.addAttribute(TextAttribute.FONT, v.getFont());
as.addAttribute(TextAttribute.FOREGROUND, v.getForeground());
if (StyleConstants.isBold(v.getAttributes())) {
as.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
}
if (StyleConstants.isItalic(v.getAttributes())) {
as.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
}
if (v.isUnderline()) {
as.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
}
if (v.isStrikeThrough()) {
as.addAttribute(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
}
if (v.isSuperscript()) {
as.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER);
}
if (v.isSubscript()) {
as.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUB);
}
// draw
AttributedCharacterIterator aci = as.getIterator(null, p0 - start, p1 - start);
SwingUtilities2.drawString(getJComponent(v),
g2d,aci,x,y);
}
|
|