/** * 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. * * @param c the editor * @param offs the offset in the document >= 0 * @param x the X coordinate >= 0 * @return the position >= 0 if the request can be computed, otherwise * a value of -1 will be returned. * @exception BadLocationException if the offset is out of range */ public static int getPositionAbove(RSyntaxTextArea c, int offs, float x, TabExpander e) throws BadLocationException { TokenOrientedView tov = (TokenOrientedView)e; Token token = tov.getTokenListForPhysicalLineAbove(offs); if (token==null) { return -1; } else if (token.getType()==Token.NULL) { int line = c.getLineOfOffset(offs); // Sure to be >0 ?? return c.getLineStartOffset(line-1); } else { return token.getListOffset(c, e, c.getMargin().left, 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. * * @param c the editor * @param offs the offset in the document >= 0 * @param x the X coordinate >= 0 * @return the position >= 0 if the request can be computed, otherwise * a value of -1 will be returned. * @exception BadLocationException if the offset is out of range */ public static int getPositionBelow(RSyntaxTextArea c, int offs, float x, TabExpander e) throws BadLocationException { TokenOrientedView tov = (TokenOrientedView)e; Token token = tov.getTokenListForPhysicalLineBelow(offs); if (token==null) { return -1; } else if (token.getType()==Token.NULL) { int line = c.getLineOfOffset(offs); // Sure to be > c.getLineCount()-1 ?? // return c.getLineStartOffset(line+1); FoldManager fm = c.getFoldManager(); line = fm.getVisibleLineBelow(line); return c.getLineStartOffset(line); } else { return token.getListOffset(c, e, c.getMargin().left, 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. * * @param c the editor * @param offs the offset in the document >= 0 * @param x the X coordinate >= 0 * @return the position >= 0 if the request can be computed, otherwise * a value of -1 will be returned. * @exception BadLocationException if the offset is out of range */ public static final int getPositionAbove(RSyntaxTextArea c, int offs, float x, TabExpander e) throws BadLocationException { TokenOrientedView tov = (TokenOrientedView)e; Token token = tov.getTokenListForPhysicalLineAbove(offs); if (token==null) return -1; // A line containing only Token.NULL is an empty line. else if (token.getType()==Token.NULL) { int line = c.getLineOfOffset(offs); // Sure to be >0 ?? return c.getLineStartOffset(line-1); } else { return token.getListOffset(c, e, c.getMargin().left, 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. * * @param c the editor * @param offs the offset in the document >= 0 * @param x the X coordinate >= 0 * @return the position >= 0 if the request can be computed, otherwise * a value of -1 will be returned. * @exception BadLocationException if the offset is out of range */ public static final int getPositionBelow(RSyntaxTextArea c, int offs, float x, TabExpander e) throws BadLocationException { TokenOrientedView tov = (TokenOrientedView)e; Token token = tov.getTokenListForPhysicalLineBelow(offs); if (token==null) return -1; // A line containing only Token.NULL is an empty line. else if (token.getType()==Token.NULL) { int line = c.getLineOfOffset(offs); // Sure to be > c.getLineCount()-1 ?? // return c.getLineStartOffset(line+1); FoldManager fm = c.getFoldManager(); line = fm.getVisibleLineBelow(line); return c.getLineStartOffset(line); } else { return token.getListOffset(c, e, c.getMargin().left, 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. * * @param c * the editor * @param offs * the offset in the document >= 0 * @param x * the X coordinate >= 0 * @return the position >= 0 if the request can be computed, otherwise a value of -1 will be returned. * @exception BadLocationException * if the offset is out of range */ public static final int getPositionAbove(RSyntaxTextArea c, int offs, float x, TabExpander e) throws BadLocationException { TokenOrientedView tov = (TokenOrientedView) e; Token token = tov.getTokenListForPhysicalLineAbove(offs); if (token == null) return -1; // A line containing only Token.NULL is an empty line. else if (token.type == Token.NULL) { int line = c.getLineOfOffset(offs); // Sure to be >0 ?? return c.getLineStartOffset(line - 1); } else { return token.getListOffset(c, e, 0, 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. * * @param c * the editor * @param offs * the offset in the document >= 0 * @param x * the X coordinate >= 0 * @return the position >= 0 if the request can be computed, otherwise a value of -1 will be returned. * @exception BadLocationException * if the offset is out of range */ public static final int getPositionBelow(RSyntaxTextArea c, int offs, float x, TabExpander e) throws BadLocationException { TokenOrientedView tov = (TokenOrientedView) e; Token token = tov.getTokenListForPhysicalLineBelow(offs); if (token == null) return -1; // A line containing only Token.NULL is an empty line. else if (token.type == Token.NULL) { int line = c.getLineOfOffset(offs); // Sure to be > c.getLineCount()-1 ?? return c.getLineStartOffset(line + 1); } else { return token.getListOffset(c, e, 0, x); } }
/** * Draw text. This can directly call the Utilities.drawTabbedText. * Sub-classes can override this method to provide any other decorations. * @param segment - the source of the text * @param x - the X origin >= 0 * @param y - the Y origin >= 0 * @param graphics - the graphics context * @param e - how to expand the tabs. If this value is null, tabs will be * expanded as a space character. * @param startOffset - starting offset of the text in the document >= 0 * @return */ public int drawText(Segment segment, int x, int y, Graphics graphics, TabExpander e, int startOffset) { graphics.setFont(graphics.getFont().deriveFont(getFontStyle())); FontMetrics fontMetrics = graphics.getFontMetrics(); int a = fontMetrics.getAscent(); int h = a + fontMetrics.getDescent(); //JPEXS: UniTools for multi fonts int w = UniTools.getTabbedTextWidth(graphics,segment,0, e, startOffset); int rX = x - 1; int rY = y - a; int rW = w + 2; int rH = h; if ((getFontStyle() & 0x10) != 0) { graphics.setColor(Color.decode("#EEEEEE")); graphics.fillRect(rX, rY, rW, rH); } graphics.setColor(getColor()); //JPEXS: UniTools for multi fonts x = UniTools.drawTabbedText(segment, x, y, graphics, e, startOffset); if ((getFontStyle() & 0x8) != 0) { graphics.setColor(Color.RED); graphics.drawRect(rX, rY, rW, rH); } return x; }
public static int getTabbedTextOffset(Segment segment, FontMetrics metrics, int tabBase,int x,TabExpander e, int startOffset){ List<Segment> segments=new ArrayList<Segment>(); List<Boolean> unis=new ArrayList<Boolean>(); Font origFont=metrics.getFont(); getSegments(origFont, segment, segments, unis); Graphics g=new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB).getGraphics(); Font uniFont = defaultUniFont.deriveFont(origFont.getStyle(),origFont.getSize2D()); int ofs=0; int totalto = 0; for(int i=0;i<segments.size();i++){ Segment seg=segments.get(i); FontMetrics fm=unis.get(i)?g.getFontMetrics(uniFont):metrics; int to = Utilities.getTabbedTextOffset(seg, fm, tabBase+ofs,x, e, startOffset); totalto += to; ofs+=fm.stringWidth(seg.toString()); if(to<seg.length()){ break; } } return totalto; }
public static int drawTabbedText(Segment segment, int x, int y, Graphics g, TabExpander e, int startOffset){ List<Segment> segments=new ArrayList<Segment>(); List<Boolean> unis=new ArrayList<Boolean>(); getSegments(g.getFont(), segment, segments, unis); Font origFont=g.getFont(); Font uniFont = defaultUniFont.deriveFont(origFont.getStyle(),origFont.getSize2D()); int ret=x; int pos=0; for(int i=0;i<segments.size();i++){ Segment seg=segments.get(i); if(unis.get(i)){ g.setFont(uniFont); }else{ g.setFont(origFont); } ret = Utilities.drawTabbedText(seg, ret, y, g, e, startOffset+pos); pos += seg.length(); } g.setFont(origFont); return ret; }
public static final int getBreakLocation(final Segment s, final FontMetrics fm, final int start, final int end, final TabExpander t, final int pos) { int offset = s.offset; int index = TextUtils.getTabbedTextOffset(s, fm, start, end, t, pos, false); int fullIndex = offset + index; BreakIterator bi = BreakIterator.getWordInstance(); bi.setText(s); if (bi.last() <= fullIndex) { return bi.last() - offset; } if (bi.isBoundary(fullIndex)) { return Character.isWhitespace(s.array[fullIndex]) ? index + 1 : index; } int prev = bi.preceding(fullIndex); if (prev == bi.first()) { return index; } return prev - offset; }
/** * Draw text. This can directly call the Utilities.drawTabbedText. * Sub-classes can override this method to provide any other decorations. * * @param segment - the source of the text * @param x - the X origin >= 0 * @param y - the Y origin >= 0 * @param graphics - the graphics context * @param e - how to expand the tabs. If this value is null, tabs will be * expanded as a space character. * @param startOffset - starting offset of the text in the document >= 0 * @return */ public int drawText(Segment segment, int x, int y, Graphics graphics, TabExpander e, int startOffset) { graphics.setFont(graphics.getFont().deriveFont(getFontStyle())); FontMetrics fontMetrics = graphics.getFontMetrics(); int a = fontMetrics.getAscent(); int h = a + fontMetrics.getDescent(); int w = Utilities.getTabbedTextWidth(segment, fontMetrics, 0, e, startOffset); int rX = x - 1; int rY = y - a; int rW = w + 2; int rH = h; if ((getFontStyle() & 0x10) != 0) { graphics.setColor(Color.decode("#EEEEEE")); graphics.fillRect(rX, rY, rW, rH); } graphics.setColor(getColor()); x = Utilities.drawTabbedText(segment, x, y, graphics, e, startOffset); if ((getFontStyle() & 0x8) != 0) { graphics.setColor(Color.RED); graphics.drawRect(rX, rY, rW, rH); } return 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. * * @param c the editor * @param offs the offset in the document >= 0 * @param x the X coordinate >= 0 * @return the position >= 0 if the request can be computed, otherwise * a value of -1 will be returned. * @exception BadLocationException if the offset is out of range */ public static final int getPositionAbove(RSyntaxTextArea c, int offs, float x, TabExpander e) throws BadLocationException { TokenOrientedView tov = (TokenOrientedView)e; Token token = tov.getTokenListForPhysicalLineAbove(offs); if (token==null) return -1; // A line containing only Token.NULL is an empty line. else if (token.type==Token.NULL) { int line = c.getLineOfOffset(offs); // Sure to be >0 ?? return c.getLineStartOffset(line-1); } else { return token.getListOffset(c, e, 0, 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. * * @param c the editor * @param offs the offset in the document >= 0 * @param x the X coordinate >= 0 * @return the position >= 0 if the request can be computed, otherwise * a value of -1 will be returned. * @exception BadLocationException if the offset is out of range */ public static final int getPositionBelow(RSyntaxTextArea c, int offs, float x, TabExpander e) throws BadLocationException { TokenOrientedView tov = (TokenOrientedView)e; Token token = tov.getTokenListForPhysicalLineBelow(offs); if (token==null) return -1; // A line containing only Token.NULL is an empty line. else if (token.type==Token.NULL) { int line = c.getLineOfOffset(offs); // Sure to be > c.getLineCount()-1 ?? // return c.getLineStartOffset(line+1); FoldManager fm = c.getFoldManager(); line = fm.getVisibleLineBelow(line); return c.getLineStartOffset(line); } else { return token.getListOffset(c, e, 0, x); } }
@Override public float getTabbedSpan(float x, TabExpander e) { int offset = getStartOffset(); int endOffset = offset + getLength(); float tabX = e.nextTabStop(x, offset++); firstTabWidth = tabX - x; while (offset < endOffset) { tabX = e.nextTabStop(tabX, offset++); } width = tabX - x; return width; }
/** * Paints the specified line onto the graphics context. Note that this method munges the offset * and count values of the segment. * * @param line * The line segment * @param tokens * The token list for the line * @param styles * The syntax style list * @param expander * The tab expander used to determine tab stops. May be null * @param gfx * The graphics context * @param x * The x co-ordinate * @param y * The y co-ordinate * @return The x co-ordinate, plus the width of the painted string */ public static int paintSyntaxLine(Segment line, Token tokens, SyntaxStyle[] styles, TabExpander expander, Graphics gfx, int x, int y) { Font defaultFont = gfx.getFont(); Color defaultColor = gfx.getColor(); int offset = 0; for (;;) { byte id = tokens.id; if (id == Token.END) { break; } int length = tokens.length; if (id == Token.NULL) { if (!defaultColor.equals(gfx.getColor())) { gfx.setColor(defaultColor); } if (!defaultFont.equals(gfx.getFont())) { gfx.setFont(defaultFont); } } else { styles[id].setGraphicsFlags(gfx, defaultFont); } line.count = length; x = Utilities.drawTabbedText(line, x, y, gfx, expander, 0); line.offset += length; offset += length; tokens = tokens.next; } return x; }
private int drawColoredText(Graphics g, int x, int y, TabExpander ex, Document doc, int p0, int p1, Element elem) throws BadLocationException { final Segment s = new Segment(); doc.getText(p0, p1 - p0, s); g.setColor(getColor(elem)); final Graphics2D g2d = (Graphics2D) g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); return Utilities.drawTabbedText(s, x, y, g, ex, p0); }
@Override public int getOffsetBeforeX(RSyntaxTextArea textArea, TabExpander e, float startX, float endBeforeX) { FontMetrics fm = textArea.getFontMetricsForTokenType(getType()); int i = textOffset; int stop = i + textCount; float x = startX; while (i<stop) { if (text[i]=='\t') { x = e.nextTabStop(x, 0); } else { x += fm.charWidth(text[i]); } if (x>endBeforeX) { // If not even the first character fits into the space, go // ahead and say the first char does fit so we don't go into // an infinite loop. int intoToken = Math.max(i-textOffset, 1); return getOffset() + intoToken; } i++; } // If we got here, the whole token fit in (endBeforeX-startX) pixels. return getOffset() + textCount - 1; }
@Override public float getWidthUpTo(int numChars, RSyntaxTextArea textArea, TabExpander e, float x0) { float width = x0; FontMetrics fm = textArea.getFontMetricsForTokenType(getType()); if (fm != null) { int w; int currentStart = textOffset; int endBefore = textOffset + numChars; for (int i = currentStart; i < endBefore; i++) { if (text[i] == '\t') { // Since TokenMaker implementations usually group all // adjacent whitespace into a single token, there // aren't usually any characters to compute a width // for here, so we check before calling. w = i - currentStart; if (w > 0) { width += fm.charsWidth(text, currentStart, w); } currentStart = i + 1; width = e.nextTabStop(width, 0); } } // Most (non-whitespace) tokens will have characters at this // point to get the widths for, so we don't check for w>0 (mini- // optimization). w = endBefore - currentStart; width += fm.charsWidth(text, currentStart, w); } return width - x0; }
/** * {@inheritDoc} */ @Override public float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart, boolean paintBG) { return paintImpl(token, g, x, y, host, e, clipStart, !paintBG, false); }
/** * {@inheritDoc} */ @Override public float paintSelected(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart, boolean useSTC) { return paintImpl(token, g, x, y, host, e, clipStart, true, useSTC); }
/** * Returns the bounding box (in the current view) of a specified position * in the model. This method is designed for line-wrapped views to use, * as it allows you to specify a "starting position" in the line, from * which the x-value is assumed to be zero. The idea is that you specify * the first character in a physical line as <code>p0</code>, as this is * the character where the x-pixel value is 0. * * @param textArea The text area containing the text. * @param s A segment in which to load the line. This is passed in so we * don't have to reallocate a new <code>Segment</code> for each * call. * @param p0 The starting position in the physical line in the document. * @param p1 The position for which to get the bounding box in the view. * @param e How to expand tabs. * @param rect The rectangle whose x- and width-values are changed to * represent the bounding box of <code>p1</code>. This is reused * to keep from needlessly reallocating Rectangles. * @param x0 The x-coordinate (pixel) marking the left-hand border of the * text. This is useful if the text area has a border, for example. * @return The bounding box in the view of the character <code>p1</code>. * @throws BadLocationException If <code>p0</code> or <code>p1</code> is * not a valid location in the specified text area's document. * @throws IllegalArgumentException If <code>p0</code> and <code>p1</code> * are not on the same line. */ public static Rectangle getLineWidthUpTo(RSyntaxTextArea textArea, Segment s, int p0, int p1, TabExpander e, Rectangle rect, int x0) throws BadLocationException { RSyntaxDocument doc = (RSyntaxDocument)textArea.getDocument(); // Ensure p0 and p1 are valid document positions. if (p0<0) throw new BadLocationException("Invalid document position", p0); else if (p1>doc.getLength()) throw new BadLocationException("Invalid document position", p1); // Ensure p0 and p1 are in the same line, and get the start/end // offsets for that line. Element map = doc.getDefaultRootElement(); int lineNum = map.getElementIndex(p0); // We do ">1" because p1 might be the first position on the next line // or the last position on the previous one. // if (lineNum!=map.getElementIndex(p1)) if (Math.abs(lineNum-map.getElementIndex(p1))>1) throw new IllegalArgumentException("p0 and p1 are not on the " + "same line (" + p0 + ", " + p1 + ")."); // Get the token list. Token t = doc.getTokenListForLine(lineNum); // Modify the token list 't' to begin at p0 (but still have correct // token types, etc.), and get the x-location (in pixels) of the // beginning of this new token list. TokenSubList subList = TokenUtils.getSubTokenList(t, p0, e, textArea, 0, tempToken); t = subList.tokenList; rect = t.listOffsetToView(textArea, e, p1, x0, rect); return rect; }
public int getOffsetBeforeX(RSyntaxTextArea textArea, TabExpander e, float startX, float endBeforeX) { FontMetrics fm = textArea.getFontMetricsForTokenType(getType()); int i = textOffset; int stop = i + textCount; float x = startX; while (i<stop) { if (text[i]=='\t') x = e.nextTabStop(x, 0); else x += fm.charWidth(text[i]); if (x>endBeforeX) { // If not even the first character fits into the space, go // ahead and say the first char does fit so we don't go into // an infinite loop. int intoToken = Math.max(i-textOffset, 1); return getOffset() + intoToken; } i++; } // If we got here, the whole token fit in (endBeforeX-startX) pixels. return getOffset() + textCount - 1; }
public float getWidthUpTo(int numChars, RSyntaxTextArea textArea, TabExpander e, float x0) { float width = x0; FontMetrics fm = textArea.getFontMetricsForTokenType(getType()); if (fm != null) { int w; int currentStart = textOffset; int endBefore = textOffset + numChars; for (int i = currentStart; i < endBefore; i++) { if (text[i] == '\t') { // Since TokenMaker implementations usually group all // adjacent whitespace into a single token, there // aren't usually any characters to compute a width // for here, so we check before calling. w = i - currentStart; if (w > 0) width += fm.charsWidth(text, currentStart, w); currentStart = i + 1; width = e.nextTabStop(width, 0); } } // Most (non-whitespace) tokens will have characters at this // point to get the widths for, so we don't check for w>0 (mini- // optimization). w = endBefore - currentStart; width += fm.charsWidth(text, currentStart, w); } return width - x0; }
/** * Paints the specified line onto the graphics context. Note that this method munges the offset * and count values of the segment. * * @param line * The line segment * @param tokens * The token list for the line * @param styles * The syntax style list * @param expander * The tab expander used to determine tab stops. May be null * @param gfx * The graphics context * @param x * The x co-ordinate * @param y * The y co-ordinate * @return The x co-ordinate, plus the width of the painted string */ public static int paintSyntaxLine(Segment line, Token tokens, SyntaxStyle[] styles, TabExpander expander, Graphics gfx, int x, int y) { Font defaultFont = gfx.getFont(); Color defaultColor = gfx.getColor(); for (;;) { byte id = tokens.id; if (id == Token.END) { break; } int length = tokens.length; if (id == Token.NULL) { if (!defaultColor.equals(gfx.getColor())) { gfx.setColor(defaultColor); } if (!defaultFont.equals(gfx.getFont())) { gfx.setFont(defaultFont); } } else { styles[id].setGraphicsFlags(gfx, defaultFont); } line.count = length; x = Utilities.drawTabbedText(line, x, y, gfx, expander, 0); line.offset += length; tokens = tokens.next; } return x; }
/** * Returns the bounding box (in the current view) of a specified position in the model. This method is designed for * line-wrapped views to use, as it allows you to specify a "starting position" in the line, from which the x-value * is assumed to be zero. The idea is that you specify the first character in a physical line as <code>p0</code>, as * this is the character where the x-pixel value is 0. * * @param textArea * The text area containing the text. * @param s * A segment in which to load the line. This is passed in so we don't have to reallocate a new * <code>Segment</code> for each call. * @param p0 * The starting position in the physical line in the document. * @param p1 * The position for which to get the bounding box in the view. * @param e * How to expand tabs. * @param rect * The rectangle whose x- and width-values are changed to represent the bounding box of <code>p1</code>. * This is reused to keep from needlessly reallocating Rectangles. * @param x0 * The x-coordinate (pixel) marking the left-hand border of the text. This is useful if the text area has * a border, for example. * @return The bounding box in the view of the character <code>p1</code>. * @throws BadLocationException * If <code>p0</code> or <code>p1</code> is not a valid location in the specified text area's document. * @throws IllegalArgumentException * If <code>p0</code> and <code>p1</code> are not on the same line. */ public static Rectangle getLineWidthUpTo(RSyntaxTextArea textArea, Segment s, int p0, int p1, TabExpander e, Rectangle rect, int x0) throws BadLocationException { RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument(); // Ensure p0 and p1 are valid document positions. if (p0 < 0) throw new BadLocationException("Invalid document position", p0); else if (p1 > doc.getLength()) throw new BadLocationException("Invalid document position", p1); // Ensure p0 and p1 are in the same line, and get the start/end // offsets for that line. Element map = doc.getDefaultRootElement(); int lineNum = map.getElementIndex(p0); // We do ">1" because p1 might be the first position on the next line // or the last position on the previous one. // if (lineNum!=map.getElementIndex(p1)) if (Math.abs(lineNum - map.getElementIndex(p1)) > 1) throw new IllegalArgumentException("p0 and p1 are not on the " + "same line (" + p0 + ", " + p1 + ")."); // Get the token list. Token t = doc.getTokenListForLine(lineNum); // Modify the token list 't' to begin at p0 (but still have correct // token types, etc.), and get the x-location (in pixels) of the // beginning of this new token list. makeTokenListStartAt(t, p0, e, textArea, 0); rect = t.listOffsetToView(textArea, e, p1, x0, rect); return rect; }
/** * Returns the width of a specified number of characters in this token. For example, for the token "while", * specifying a value of <code>3</code> here returns the width of the "whi" portion of the token. * <p> * * @param numChars * The number of characters for which to get the width. * @param textArea * The text area in which this token is being painted. * @param e * How to expand tabs. This value cannot be <code>null</code>. * @param x0 * The pixel-location at which this token begins. This is needed because of tabs. * @return The width of the specified number of characters in this token. * @see #getWidth */ public float getWidthUpTo(int numChars, RSyntaxTextArea textArea, TabExpander e, float x0) { float width = x0; FontMetrics fm = textArea.getFontMetricsForTokenType(type); if (fm != null) { int w; int currentStart = textOffset; int endBefore = textOffset + numChars; for (int i = currentStart; i < endBefore; i++) { if (text[i] == '\t') { // Since TokenMaker implementations usually group all // adjacent whitespace into a single token, there // aren't usually any characters to compute a width // for here, so we check before calling. w = i - currentStart; if (w > 0) width += fm.charsWidth(text, currentStart, w); currentStart = i + 1; width = e.nextTabStop(width, 0); } } // Most (non-whitespace) tokens will have characters at this // point to get the widths for, so we don't check for w>0 (mini- // optimization). w = endBefore - currentStart; width += fm.charsWidth(text, currentStart, w); } return width - x0; }
/** * Returns the position in the document that represents the last character in the token that will fit into * <code>endBeforeX-startX</code> pixels. For example, if you're using a monospaced 8-pixel-per-character font, have * the token "while" and <code>startX</code> is <code>0</code> and <code>endBeforeX</code> is <code>30</code>, this * method will return the document position of the "i" in "while", because the "i" ends at pixel <code>24</code>, * while the "l" ends at <code>32</code>. If not even the first character fits in <code>endBeforeX-startX</code>, * the first character's position is still returned so calling methods don't go into infinite loops. * * @param textArea * The text area in which this token is being painted. * @param e * How to expand tabs. * @param startX * The x-coordinate at which the token will be painted. This is needed because of tabs. * @param endBeforeX * The x-coordinate for which you want to find the last character of <code>t</code> which comes before * it. * @return The last document position that will fit in the specified amount of pixels. */ /* * @see #getTokenListOffsetBeforeX FIXME: This method does not compute correctly! It needs to be abstract and * implemented by subclasses. */ public int getOffsetBeforeX(RSyntaxTextArea textArea, TabExpander e, float startX, float endBeforeX) { FontMetrics fm = textArea.getFontMetricsForTokenType(type); int i = textOffset; int stop = i + textCount; float x = startX; while (i < stop) { if (text[i] == '\t') x = e.nextTabStop(x, 0); else x += fm.charWidth(text[i]); if (x > endBeforeX) { // If not even the first character fits into the space, go // ahead and say the first char does fit so we don't go into // an infinite loop. int intoToken = Math.max(i - textOffset, 1); return offset + intoToken; } i++; } // If we got here, the whole token fit in (endBeforeX-startX) pixels. return offset + textCount - 1; }