diff options
Diffstat (limited to 'libjava/classpath/javax/swing/text/Utilities.java')
-rw-r--r-- | libjava/classpath/javax/swing/text/Utilities.java | 730 |
1 files changed, 0 insertions, 730 deletions
diff --git a/libjava/classpath/javax/swing/text/Utilities.java b/libjava/classpath/javax/swing/text/Utilities.java deleted file mode 100644 index 6221392..0000000 --- a/libjava/classpath/javax/swing/text/Utilities.java +++ /dev/null @@ -1,730 +0,0 @@ -/* Utilities.java -- - Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package javax.swing.text; - -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Point; -import java.text.BreakIterator; - -import javax.swing.text.Position.Bias; - -/** - * A set of utilities to deal with text. This is used by several other classes - * inside this package. - * - * @author Roman Kennke (roman@ontographics.com) - * @author Robert Schuster (robertschuster@fsfe.org) - */ -public class Utilities -{ - - /** - * Creates a new <code>Utilities</code> object. - */ - public Utilities() - { - // Nothing to be done here. - } - - /** - * Draws the given text segment. Contained tabs and newline characters - * are taken into account. Tabs are expanded using the - * specified {@link TabExpander}. - * - * - * The X and Y coordinates denote the start of the <em>baseline</em> where - * the text should be drawn. - * - * @param s the text fragment to be drawn. - * @param x the x position for drawing. - * @param y the y position for drawing. - * @param g the {@link Graphics} context for drawing. - * @param e the {@link TabExpander} which specifies the Tab-expanding - * technique. - * @param startOffset starting offset in the text. - * @return the x coordinate at the end of the drawn text. - */ - public static final int drawTabbedText(Segment s, int x, int y, Graphics g, - TabExpander e, int startOffset) - { - // This buffers the chars to be drawn. - char[] buffer = s.array; - - // The font metrics of the current selected font. - FontMetrics metrics = g.getFontMetrics(); - - int ascent = metrics.getAscent(); - - // The current x and y pixel coordinates. - int pixelX = x; - - int pos = s.offset; - int len = 0; - - int end = s.offset + s.count; - - for (int offset = s.offset; offset < end; ++offset) - { - char c = buffer[offset]; - switch (c) - { - case '\t': - if (len > 0) { - g.drawChars(buffer, pos, len, pixelX, y); - pixelX += metrics.charsWidth(buffer, pos, len); - len = 0; - } - pos = offset+1; - if (e != null) - pixelX = (int) e.nextTabStop((float) pixelX, startOffset + offset - - s.offset); - else - pixelX += metrics.charWidth(' '); - x = pixelX; - break; - case '\n': - case '\r': - if (len > 0) { - g.drawChars(buffer, pos, len, pixelX, y); - pixelX += metrics.charsWidth(buffer, pos, len); - len = 0; - } - x = pixelX; - break; - default: - len += 1; - } - } - - if (len > 0) - { - g.drawChars(buffer, pos, len, pixelX, y); - pixelX += metrics.charsWidth(buffer, pos, len); - } - - return pixelX; - } - - /** - * Determines the width, that the given text <code>s</code> would take - * if it was printed with the given {@link java.awt.FontMetrics} on the - * specified screen position. - * @param s the text fragment - * @param metrics the font metrics of the font to be used - * @param x the x coordinate of the point at which drawing should be done - * @param e the {@link TabExpander} to be used - * @param startOffset the index in <code>s</code> where to start - * @returns the width of the given text s. This takes tabs and newlines - * into account. - */ - public static final int getTabbedTextWidth(Segment s, FontMetrics metrics, - int x, TabExpander e, - int startOffset) - { - // This buffers the chars to be drawn. - char[] buffer = s.array; - - // The current x coordinate. - int pixelX = x; - - // The current maximum width. - int maxWidth = 0; - - int end = s.offset + s.count; - int count = 0; - for (int offset = s.offset; offset < end; offset++) - { - switch (buffer[offset]) - { - case '\t': - // In case we have a tab, we just 'jump' over the tab. - // When we have no tab expander we just use the width of 'm'. - if (e != null) - pixelX = (int) e.nextTabStop(pixelX, - startOffset + offset - s.offset); - else - pixelX += metrics.charWidth(' '); - break; - case '\n': - // In case we have a newline, we must 'draw' - // the buffer and jump on the next line. - pixelX += metrics.charsWidth(buffer, offset - count, count); - count = 0; - break; - default: - count++; - } - } - - // Take the last line into account. - pixelX += metrics.charsWidth(buffer, end - count, count); - - return pixelX - x; - } - - /** - * Provides a facility to map screen coordinates into a model location. For a - * given text fragment and start location within this fragment, this method - * determines the model location so that the resulting fragment fits best - * into the span <code>[x0, x]</code>. - * - * The parameter <code>round</code> controls which model location is returned - * if the view coordinates are on a character: If <code>round</code> is - * <code>true</code>, then the result is rounded up to the next character, so - * that the resulting fragment is the smallest fragment that is larger than - * the specified span. If <code>round</code> is <code>false</code>, then the - * resulting fragment is the largest fragment that is smaller than the - * specified span. - * - * @param s the text segment - * @param fm the font metrics to use - * @param x0 the starting screen location - * @param x the target screen location at which the requested fragment should - * end - * @param te the tab expander to use; if this is <code>null</code>, TABs are - * expanded to one space character - * @param p0 the starting model location - * @param round if <code>true</code> round up to the next location, otherwise - * round down to the current location - * - * @return the model location, so that the resulting fragment fits within the - * specified span - */ - public static final int getTabbedTextOffset(Segment s, FontMetrics fm, int x0, - int x, TabExpander te, int p0, - boolean round) - { - int found = s.count; - int currentX = x0; - int nextX = currentX; - - int end = s.offset + s.count; - for (int pos = s.offset; pos < end && found == s.count; pos++) - { - char nextChar = s.array[pos]; - - if (nextChar != '\t') - nextX += fm.charWidth(nextChar); - else - { - if (te == null) - nextX += fm.charWidth(' '); - else - nextX += ((int) te.nextTabStop(nextX, p0 + pos - s.offset)); - } - - if (x >= currentX && x < nextX) - { - // Found position. - if ((! round) || ((x - currentX) < (nextX - x))) - { - found = pos - s.offset; - } - else - { - found = pos + 1 - s.offset; - } - } - currentX = nextX; - } - - return found; - } - - /** - * Provides a facility to map screen coordinates into a model location. For a - * given text fragment and start location within this fragment, this method - * determines the model location so that the resulting fragment fits best - * into the span <code>[x0, x]</code>. - * - * This method rounds up to the next location, so that the resulting fragment - * will be the smallest fragment of the text, that is greater than the - * specified span. - * - * @param s the text segment - * @param fm the font metrics to use - * @param x0 the starting screen location - * @param x the target screen location at which the requested fragment should - * end - * @param te the tab expander to use; if this is <code>null</code>, TABs are - * expanded to one space character - * @param p0 the starting model location - * - * @return the model location, so that the resulting fragment fits within the - * specified span - */ - public static final int getTabbedTextOffset(Segment s, FontMetrics fm, int x0, - int x, TabExpander te, int p0) - { - return getTabbedTextOffset(s, fm, x0, x, te, p0, true); - } - - /** - * Finds the start of the next word for the given offset. - * - * @param c - * the text component - * @param offs - * the offset in the document - * @return the location in the model of the start of the next word. - * @throws BadLocationException - * if the offset is invalid. - */ - public static final int getNextWord(JTextComponent c, int offs) - throws BadLocationException - { - if (offs < 0 || offs > (c.getText().length() - 1)) - throw new BadLocationException("invalid offset specified", offs); - String text = c.getText(); - BreakIterator wb = BreakIterator.getWordInstance(); - wb.setText(text); - - int last = wb.following(offs); - int current = wb.next(); - int cp; - - while (current != BreakIterator.DONE) - { - for (int i = last; i < current; i++) - { - cp = text.codePointAt(i); - - // Return the last found bound if there is a letter at the current - // location or is not whitespace (meaning it is a number or - // punctuation). The first case means that 'last' denotes the - // beginning of a word while the second case means it is the start - // of something else. - if (Character.isLetter(cp) - || !Character.isWhitespace(cp)) - return last; - } - last = current; - current = wb.next(); - } - - throw new BadLocationException("no more words", offs); - } - - /** - * Finds the start of the previous word for the given offset. - * - * @param c - * the text component - * @param offs - * the offset in the document - * @return the location in the model of the start of the previous word. - * @throws BadLocationException - * if the offset is invalid. - */ - public static final int getPreviousWord(JTextComponent c, int offs) - throws BadLocationException - { - String text = c.getText(); - - if (offs <= 0 || offs > text.length()) - throw new BadLocationException("invalid offset specified", offs); - - BreakIterator wb = BreakIterator.getWordInstance(); - wb.setText(text); - int last = wb.preceding(offs); - int current = wb.previous(); - int cp; - - while (current != BreakIterator.DONE) - { - for (int i = last; i < offs; i++) - { - cp = text.codePointAt(i); - - // Return the last found bound if there is a letter at the current - // location or is not whitespace (meaning it is a number or - // punctuation). The first case means that 'last' denotes the - // beginning of a word while the second case means it is the start - // of some else. - if (Character.isLetter(cp) - || !Character.isWhitespace(cp)) - return last; - } - last = current; - current = wb.previous(); - } - - return 0; - } - - /** - * Finds the start of a word for the given location. - * @param c the text component - * @param offs the offset location - * @return the location of the word beginning - * @throws BadLocationException if the offset location is invalid - */ - public static final int getWordStart(JTextComponent c, int offs) - throws BadLocationException - { - String text = c.getText(); - - if (offs < 0 || offs > text.length()) - throw new BadLocationException("invalid offset specified", offs); - - BreakIterator wb = BreakIterator.getWordInstance(); - wb.setText(text); - - if (wb.isBoundary(offs)) - return offs; - - return wb.preceding(offs); - } - - /** - * Finds the end of a word for the given location. - * @param c the text component - * @param offs the offset location - * @return the location of the word end - * @throws BadLocationException if the offset location is invalid - */ - public static final int getWordEnd(JTextComponent c, int offs) - throws BadLocationException - { - if (offs < 0 || offs >= c.getText().length()) - throw new BadLocationException("invalid offset specified", offs); - - String text = c.getText(); - BreakIterator wb = BreakIterator.getWordInstance(); - wb.setText(text); - return wb.following(offs); - } - - /** - * Get the model position of the end of the row that contains the - * specified model position. Return null if the given JTextComponent - * does not have a size. - * @param c the JTextComponent - * @param offs the model position - * @return the model position of the end of the row containing the given - * offset - * @throws BadLocationException if the offset is invalid - */ - public static final int getRowEnd(JTextComponent c, int offs) - throws BadLocationException - { - String text = c.getText(); - if (text == null) - return -1; - - // Do a binary search for the smallest position X > offs - // such that that character at positino X is not on the same - // line as the character at position offs - int high = offs + ((text.length() - 1 - offs) / 2); - int low = offs; - int oldHigh = text.length() + 1; - while (true) - { - if (c.modelToView(high).y != c.modelToView(offs).y) - { - oldHigh = high; - high = low + ((high + 1 - low) / 2); - if (oldHigh == high) - return high - 1; - } - else - { - low = high; - high += ((oldHigh - high) / 2); - if (low == high) - return low; - } - } - } - - /** - * Get the model position of the start of the row that contains the specified - * model position. Return null if the given JTextComponent does not have a - * size. - * - * @param c the JTextComponent - * @param offs the model position - * @return the model position of the start of the row containing the given - * offset - * @throws BadLocationException if the offset is invalid - */ - public static final int getRowStart(JTextComponent c, int offs) - throws BadLocationException - { - String text = c.getText(); - if (text == null) - return -1; - - // Do a binary search for the greatest position X < offs - // such that the character at position X is not on the same - // row as the character at position offs - int high = offs; - int low = 0; - int oldLow = 0; - while (true) - { - if (c.modelToView(low).y != c.modelToView(offs).y) - { - oldLow = low; - low = high - ((high + 1 - low) / 2); - if (oldLow == low) - return low + 1; - } - else - { - high = low; - low -= ((low - oldLow) / 2); - if (low == high) - return low; - } - } - } - - /** - * Determine where to break the text in the given Segment, attempting to find - * a word boundary. - * @param s the Segment that holds the text - * @param metrics the font metrics used for calculating the break point - * @param x0 starting view location representing the start of the text - * @param x the target view location - * @param e the TabExpander used for expanding tabs (if this is null tabs - * are expanded to 1 space) - * @param startOffset the offset in the Document of the start of the text - * @return the offset at which we should break the text - */ - public static final int getBreakLocation(Segment s, FontMetrics metrics, - int x0, int x, TabExpander e, - int startOffset) - { - int mark = Utilities.getTabbedTextOffset(s, metrics, x0, x, e, startOffset, - false); - int breakLoc = mark; - // If mark is equal to the end of the string, just use that position. - if (mark < s.count - 1) - { - for (int i = s.offset + mark; i >= s.offset; i--) - { - char ch = s.array[i]; - if (ch < 256) - { - // For ASCII simply scan backwards for whitespace. - if (Character.isWhitespace(ch)) - { - breakLoc = i - s.offset + 1; - break; - } - } - else - { - // Only query BreakIterator for complex chars. - BreakIterator bi = BreakIterator.getLineInstance(); - bi.setText(s); - int pos = bi.preceding(i + 1); - if (pos > s.offset) - { - breakLoc = breakLoc - s.offset; - } - break; - } - } - } - return breakLoc; - } - - /** - * Returns the paragraph element in the text component <code>c</code> at - * the specified location <code>offset</code>. - * - * @param c the text component - * @param offset the offset of the paragraph element to return - * - * @return the paragraph element at <code>offset</code> - */ - public static final Element getParagraphElement(JTextComponent c, int offset) - { - Document doc = c.getDocument(); - Element par = null; - if (doc instanceof StyledDocument) - { - StyledDocument styledDoc = (StyledDocument) doc; - par = styledDoc.getParagraphElement(offset); - } - else - { - Element root = c.getDocument().getDefaultRootElement(); - int parIndex = root.getElementIndex(offset); - par = root.getElement(parIndex); - } - return par; - } - - /** - * Returns the document position that is closest above to the specified x - * coordinate in the row containing <code>offset</code>. - * - * @param c the text component - * @param offset the offset - * @param x the x coordinate - * - * @return the document position that is closest above to the specified x - * coordinate in the row containing <code>offset</code> - * - * @throws BadLocationException if <code>offset</code> is not a valid offset - */ - public static final int getPositionAbove(JTextComponent c, int offset, int x) - throws BadLocationException - { - int offs = getRowStart(c, offset); - - if(offs == -1) - return -1; - - // Effectively calculates the y value of the previous line. - Point pt = c.modelToView(offs-1).getLocation(); - - pt.x = x; - - // Calculate a simple fitting offset. - offs = c.viewToModel(pt); - - // Find out the real x positions of the calculated character and its - // neighbour. - int offsX = c.modelToView(offs).getLocation().x; - int offsXNext = c.modelToView(offs+1).getLocation().x; - - // Chose the one which is nearer to us and return its offset. - if (Math.abs(offsX-x) <= Math.abs(offsXNext-x)) - return offs; - else - return offs+1; - } - - /** - * Returns the document position that is closest below to the specified x - * coordinate in the row containing <code>offset</code>. - * - * @param c the text component - * @param offset the offset - * @param x the x coordinate - * - * @return the document position that is closest above to the specified x - * coordinate in the row containing <code>offset</code> - * - * @throws BadLocationException if <code>offset</code> is not a valid offset - */ - public static final int getPositionBelow(JTextComponent c, int offset, int x) - throws BadLocationException - { - int offs = getRowEnd(c, offset); - - if(offs == -1) - return -1; - - Point pt = null; - - // Note: Some views represent the position after the last - // typed character others do not. Converting offset 3 in "a\nb" - // in a PlainView will return a valid rectangle while in a - // WrappedPlainView this will throw a BadLocationException. - // This behavior has been observed in the RI. - try - { - // Effectively calculates the y value of the next line. - pt = c.modelToView(offs+1).getLocation(); - } - catch(BadLocationException ble) - { - return offset; - } - - pt.x = x; - - // Calculate a simple fitting offset. - offs = c.viewToModel(pt); - - if (offs == c.getDocument().getLength()) - return offs; - - // Find out the real x positions of the calculated character and its - // neighbour. - int offsX = c.modelToView(offs).getLocation().x; - int offsXNext = c.modelToView(offs+1).getLocation().x; - - // Chose the one which is nearer to us and return its offset. - if (Math.abs(offsX-x) <= Math.abs(offsXNext-x)) - return offs; - else - return offs+1; - } - - /** This is an internal helper method which is used by the - * <code>javax.swing.text</code> package. It simply delegates the - * call to a method with the same name on the <code>NavigationFilter</code> - * of the provided <code>JTextComponent</code> (if it has one) or its UI. - * - * If the underlying method throws a <code>BadLocationException</code> it - * will be swallowed and the initial offset is returned. - */ - static int getNextVisualPositionFrom(JTextComponent t, int offset, int direction) - { - NavigationFilter nf = t.getNavigationFilter(); - - try - { - return (nf != null) - ? nf.getNextVisualPositionFrom(t, - offset, - Bias.Forward, - direction, - new Position.Bias[1]) - : t.getUI().getNextVisualPositionFrom(t, - offset, - Bias.Forward, - direction, - new Position.Bias[1]); - } - catch (BadLocationException ble) - { - return offset; - } - - } - -} |