Ejemplo n.º 1
0
 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;
 }
Ejemplo n.º 2
0
  public int getListOffset(RSyntaxTextArea textArea, TabExpander e, float x0, float x) {

    // If the coordinate in question is before this line's start, quit.
    if (x0 >= x) return getOffset();

    float currX = x0; // x-coordinate of current char.
    float nextX = x0; // x-coordinate of next char.
    float stableX = x0; // Cached ending x-coord. of last tab or token.
    TokenImpl token = this;
    int last = getOffset();
    FontMetrics fm = null;

    while (token != null && token.isPaintable()) {

      fm = textArea.getFontMetricsForTokenType(token.getType());
      char[] text = token.text;
      int start = token.textOffset;
      int end = start + token.textCount;

      for (int i = start; i < end; i++) {
        currX = nextX;
        if (text[i] == '\t') {
          nextX = e.nextTabStop(nextX, 0);
          stableX = nextX; // Cache ending x-coord. of tab.
          start = i + 1; // Do charsWidth() from next char.
        } else {
          nextX = stableX + fm.charsWidth(text, start, i - start + 1);
        }
        if (x >= currX && x < nextX) {
          if ((x - currX) < (nextX - x)) {
            return last + i - token.textOffset;
          }
          return last + i + 1 - token.textOffset;
        }
      }

      stableX = nextX; // Cache ending x-coordinate of token.
      last += token.textCount;
      token = (TokenImpl) token.getNextToken();
    }

    // If we didn't find anything, return the end position of the text.
    return last;
  }
Ejemplo n.º 3
0
  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;
  }
  /**
   * Paints this token, using special symbols for whitespace characters.
   *
   * @param g The graphics context in which to paint.
   * @param x The x-coordinate at which to paint.
   * @param y The y-coordinate at which to paint.
   * @param host The text area this token is in.
   * @param e How to expand tabs.
   * @param clipStart The left boundary of the clip rectangle in which we're painting. This
   *     optimizes painting by allowing us to not paint not paint when this token is "to the left"
   *     of the clip rectangle.
   * @return The x-coordinate representing the end of the painted text.
   */
  public final float paint(
      Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart) {

    int origX = (int) x;
    int end = textOffset + textCount;
    float nextX = x;
    int flushLen = 0;
    int flushIndex = textOffset;
    Color fg = host.getForegroundForToken(this);
    Color bg = host.getBackgroundForTokenType(type);
    g.setFont(host.getFontForTokenType(type));
    FontMetrics fm = host.getFontMetricsForTokenType(type);

    int ascent = fm.getAscent();
    int height = fm.getHeight();

    for (int i = textOffset; i < end; i++) {

      switch (text[i]) {
        case '\t':

          // Fill in background.
          nextX = x + fm.charsWidth(text, flushIndex, flushLen);
          float nextNextX = e.nextTabStop(nextX, 0);
          if (bg != null) {
            paintBackground(x, y, nextNextX - x, height, g, ascent, host, bg);
          }
          g.setColor(fg);

          // Paint chars cached before the tab.
          if (flushLen > 0) {
            g.drawChars(text, flushIndex, flushLen, (int) x, (int) y);
            flushLen = 0;
          }
          flushIndex = i + 1;

          // Draw an arrow representing the tab.
          int halfHeight = height / 2;
          int quarterHeight = halfHeight / 2;
          int ymid = (int) y - ascent + halfHeight;
          g.drawLine((int) nextX, ymid, (int) nextNextX, ymid);
          g.drawLine((int) nextNextX, ymid, (int) nextNextX - 4, ymid - quarterHeight);
          g.drawLine((int) nextNextX, ymid, (int) nextNextX - 4, ymid + quarterHeight);

          x = nextNextX;
          break;

        case ' ':

          // NOTE:  There is a little bit of a "fudge factor"
          // here when "smooth text" is enabled, as "width"
          // below may well not be the width given to the space
          // by fm.charsWidth() (it depends on how it places the
          // space with respect to the preceding character).
          // But, we assume the approximation is close enough for
          // our drawing a dot for the space.

          // "flushLen+1" ensures text is aligned correctly (or,
          // aligned the same as in getWidth()).
          nextX = x + fm.charsWidth(text, flushIndex, flushLen + 1);
          int width = fm.charWidth(' ');

          // Paint background.
          if (bg != null) {
            paintBackground(x, y, nextX - x, height, g, ascent, host, bg);
          }
          g.setColor(fg);

          // Paint chars before space.
          if (flushLen > 0) {
            g.drawChars(text, flushIndex, flushLen, (int) x, (int) y);
            flushLen = 0;
          }

          // Paint a dot representing the space.
          dotRect.x = nextX - width / 2.0f; // "2.0f" for FindBugs
          dotRect.y = y - ascent + height / 2.0f; // Ditto
          g.fill(dotRect);
          flushIndex = i + 1;
          x = nextX;
          break;

        case '\f':
          // ???
          // fall-through for now.

        default:
          flushLen += 1;
          break;
      }
    }

    nextX = x + fm.charsWidth(text, flushIndex, flushLen);

    if (flushLen > 0 && nextX >= clipStart) {
      if (bg != null) {
        paintBackground(x, y, nextX - x, height, g, ascent, host, bg);
      }
      g.setColor(fg);
      g.drawChars(text, flushIndex, flushLen, (int) x, (int) y);
    }

    if (host.getUnderlineForToken(this)) {
      g.setColor(fg);
      int y2 = (int) (y + 1);
      g.drawLine(origX, y2, (int) nextX, y2);
    }

    // Don't check if it's whitespace - some TokenMakers may return types
    // other than Token.WHITESPACE for spaces (such as Token.IDENTIFIER).
    // This also allows us to paint tab lines for MLC's.
    if (host.getPaintTabLines() && origX == host.getMargin().left) { // && isWhitespace()) {
      paintTabLines(origX, (int) y, (int) nextX, g, e, host);
    }

    return nextX;
  }