Example #1
0
 /**
  * Determines the preferred span for this view along an axis.
  *
  * @param axis may be either View.X_AXIS or View.Y_AXIS
  * @return the span the view would like to be rendered into >= 0. Typically the view is told to
  *     render into the span that is returned, although there is no guarantee. The parent may
  *     choose to resize or break the view.
  */
 public float getPreferredSpan(int axis) {
   switch (axis) {
     case View.X_AXIS:
       Segment buff = SegmentCache.getSharedSegment();
       Document doc = getDocument();
       int width;
       try {
         FontMetrics fm = getFontMetrics();
         doc.getText(0, doc.getLength(), buff);
         width = Utilities.getTabbedTextWidth(buff, fm, 0, this, 0);
         if (buff.count > 0) {
           Component c = getContainer();
           firstLineOffset =
               sun.swing.SwingUtilities2.getLeftSideBearing(
                   (c instanceof JComponent) ? (JComponent) c : null, fm, buff.array[buff.offset]);
           firstLineOffset = Math.max(0, -firstLineOffset);
         } else {
           firstLineOffset = 0;
         }
       } catch (BadLocationException bl) {
         width = 0;
       }
       SegmentCache.releaseSharedSegment(buff);
       return width + firstLineOffset;
     default:
       return super.getPreferredSpan(axis);
   }
 }
Example #2
0
  /** Paints the glyphs representing the given range. */
  public void paint(GlyphView v, Graphics g, Shape a, int p0, int p1) {
    sync(v);
    Segment text;
    TabExpander expander = v.getTabExpander();
    Rectangle alloc = (a instanceof Rectangle) ? (Rectangle) a : a.getBounds();

    // determine the x coordinate to render the glyphs
    int x = alloc.x;
    int p = v.getStartOffset();
    int[] justificationData = getJustificationData(v);
    if (p != p0) {
      text = v.getText(p, p0);
      int width = Utilities.getTabbedTextWidth(v, text, metrics, x, expander, p, justificationData);
      x += width;
      SegmentCache.releaseSharedSegment(text);
    }

    // determine the y coordinate to render the glyphs
    int y = alloc.y + metrics.getHeight() - metrics.getDescent();

    // render the glyphs
    text = v.getText(p0, p1);
    g.setFont(metrics.getFont());

    Utilities.drawTabbedText(v, text, x, y, g, expander, p0, justificationData);
    SegmentCache.releaseSharedSegment(text);
  }
Example #3
0
  public Shape modelToView(GlyphView v, int pos, Position.Bias bias, Shape a)
      throws BadLocationException {

    sync(v);
    Rectangle alloc = (a instanceof Rectangle) ? (Rectangle) a : a.getBounds();
    int p0 = v.getStartOffset();
    int p1 = v.getEndOffset();
    TabExpander expander = v.getTabExpander();
    Segment text;

    if (pos == p1) {
      // The caller of this is left to right and borders a right to
      // left view, return our end location.
      return new Rectangle(alloc.x + alloc.width, alloc.y, 0, metrics.getHeight());
    }
    if ((pos >= p0) && (pos <= p1)) {
      // determine range to the left of the position
      text = v.getText(p0, pos);
      int[] justificationData = getJustificationData(v);
      int width =
          Utilities.getTabbedTextWidth(v, text, metrics, alloc.x, expander, p0, justificationData);
      SegmentCache.releaseSharedSegment(text);
      return new Rectangle(alloc.x + width, alloc.y, 0, metrics.getHeight());
    }
    throw new BadLocationException("modelToView - can't convert", p1);
  }
Example #4
0
 /** Determine the span the glyphs given a start location (for tab expansion). */
 public float getSpan(GlyphView v, int p0, int p1, TabExpander e, float x) {
   sync(v);
   Segment text = v.getText(p0, p1);
   int[] justificationData = getJustificationData(v);
   int width = Utilities.getTabbedTextWidth(v, text, metrics, (int) x, e, p0, justificationData);
   SegmentCache.releaseSharedSegment(text);
   return width;
 }
Example #5
0
 /**
  * Determines the best location (in the model) to break the given view. This method attempts to
  * break on a whitespace location. If a whitespace location can't be found, the nearest character
  * location is returned.
  *
  * @param v the view
  * @param p0 the location in the model where the fragment should start its representation >= 0
  * @param pos the graphic location along the axis that the broken view would occupy >= 0; this may
  *     be useful for things like tab calculations
  * @param len specifies the distance into the view where a potential break is desired >= 0
  * @return the model location desired for a break
  * @see View#breakView
  */
 public int getBoundedPosition(GlyphView v, int p0, float x, float len) {
   sync(v);
   TabExpander expander = v.getTabExpander();
   Segment s = v.getText(p0, v.getEndOffset());
   int[] justificationData = getJustificationData(v);
   int index =
       Utilities.getTabbedTextOffset(
           v, s, metrics, (int) x, (int) (x + len), expander, p0, false, justificationData);
   SegmentCache.releaseSharedSegment(s);
   int p1 = p0 + index;
   return p1;
 }
Example #6
0
  /**
   * Provides a mapping from the view coordinate space to the logical coordinate space of the model.
   *
   * @param v the view containing the view coordinates
   * @param x the X coordinate
   * @param y the Y coordinate
   * @param a the allocated region to render into
   * @param biasReturn always returns <code>Position.Bias.Forward</code> as the zero-th element of
   *     this array
   * @return the location within the model that best represents the given point in the view
   * @see View#viewToModel
   */
  public int viewToModel(GlyphView v, float x, float y, Shape a, Position.Bias[] biasReturn) {

    sync(v);
    Rectangle alloc = (a instanceof Rectangle) ? (Rectangle) a : a.getBounds();
    int p0 = v.getStartOffset();
    int p1 = v.getEndOffset();
    TabExpander expander = v.getTabExpander();
    Segment text = v.getText(p0, p1);
    int[] justificationData = getJustificationData(v);
    int offs =
        Utilities.getTabbedTextOffset(
            v, text, metrics, alloc.x, (int) x, expander, p0, justificationData);
    SegmentCache.releaseSharedSegment(text);
    int retValue = p0 + offs;
    if (retValue == p1) {
      // No need to return backward bias as GlyphPainter1 is used for
      // ltr text only.
      retValue--;
    }
    biasReturn[0] = Position.Bias.Forward;
    return retValue;
  }
  /**
   * 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.
   *
   * @param v the view to use
   * @param pos the position to convert >= 0
   * @param a the allocated region to render into
   * @param direction the direction from the current position that can be thought of as the arrow
   *     keys typically found on a keyboard. This may be SwingConstants.WEST, SwingConstants.EAST,
   *     SwingConstants.NORTH, or SwingConstants.SOUTH.
   * @return the location within the model that best represents the next location visual position.
   * @exception BadLocationException
   * @exception IllegalArgumentException for an invalid direction
   */
  public int getNextVisualPositionFrom(
      GlyphView v, int pos, Position.Bias b, Shape a, int direction, Position.Bias[] biasRet)
      throws BadLocationException {

    int startOffset = v.getStartOffset();
    int endOffset = v.getEndOffset();
    Segment text;
    AbstractDocument doc;
    boolean viewIsLeftToRight;
    TextHitInfo currentHit, nextHit;

    switch (direction) {
      case View.NORTH:
        break;
      case View.SOUTH:
        break;
      case View.EAST:
        doc = (AbstractDocument) v.getDocument();
        viewIsLeftToRight = doc.isLeftToRight(startOffset, endOffset);

        if (startOffset == doc.getLength()) {
          if (pos == -1) {
            biasRet[0] = Position.Bias.Forward;
            return startOffset;
          }
          // End case for bidi text where newline is at beginning
          // of line.
          return -1;
        }
        if (pos == -1) {
          // Entering view from the left.
          if (viewIsLeftToRight) {
            biasRet[0] = Position.Bias.Forward;
            return startOffset;
          } else {
            text = v.getText(endOffset - 1, endOffset);
            char c = text.array[text.offset];
            SegmentCache.releaseSharedSegment(text);
            if (c == '\n') {
              biasRet[0] = Position.Bias.Forward;
              return endOffset - 1;
            }
            biasRet[0] = Position.Bias.Backward;
            return endOffset;
          }
        }
        if (b == Position.Bias.Forward) currentHit = TextHitInfo.afterOffset(pos - startOffset);
        else currentHit = TextHitInfo.beforeOffset(pos - startOffset);
        nextHit = layout.getNextRightHit(currentHit);
        if (nextHit == null) {
          return -1;
        }
        if (viewIsLeftToRight != layout.isLeftToRight()) {
          // If the layout's base direction is different from
          // this view's run direction, we need to use the weak
          // carrat.
          nextHit = layout.getVisualOtherHit(nextHit);
        }
        pos = nextHit.getInsertionIndex() + startOffset;

        if (pos == endOffset) {
          // A move to the right from an internal position will
          // only take us to the endOffset in a left to right run.
          text = v.getText(endOffset - 1, endOffset);
          char c = text.array[text.offset];
          SegmentCache.releaseSharedSegment(text);
          if (c == '\n') {
            return -1;
          }
          biasRet[0] = Position.Bias.Backward;
        } else {
          biasRet[0] = Position.Bias.Forward;
        }
        return pos;
      case View.WEST:
        doc = (AbstractDocument) v.getDocument();
        viewIsLeftToRight = doc.isLeftToRight(startOffset, endOffset);

        if (startOffset == doc.getLength()) {
          if (pos == -1) {
            biasRet[0] = Position.Bias.Forward;
            return startOffset;
          }
          // End case for bidi text where newline is at beginning
          // of line.
          return -1;
        }
        if (pos == -1) {
          // Entering view from the right
          if (viewIsLeftToRight) {
            text = v.getText(endOffset - 1, endOffset);
            char c = text.array[text.offset];
            SegmentCache.releaseSharedSegment(text);
            if ((c == '\n') || Character.isSpaceChar(c)) {
              biasRet[0] = Position.Bias.Forward;
              return endOffset - 1;
            }
            biasRet[0] = Position.Bias.Backward;
            return endOffset;
          } else {
            biasRet[0] = Position.Bias.Forward;
            return startOffset;
          }
        }
        if (b == Position.Bias.Forward) currentHit = TextHitInfo.afterOffset(pos - startOffset);
        else currentHit = TextHitInfo.beforeOffset(pos - startOffset);
        nextHit = layout.getNextLeftHit(currentHit);
        if (nextHit == null) {
          return -1;
        }
        if (viewIsLeftToRight != layout.isLeftToRight()) {
          // If the layout's base direction is different from
          // this view's run direction, we need to use the weak
          // carrat.
          nextHit = layout.getVisualOtherHit(nextHit);
        }
        pos = nextHit.getInsertionIndex() + startOffset;

        if (pos == endOffset) {
          // A move to the left from an internal position will
          // only take us to the endOffset in a right to left run.
          text = v.getText(endOffset - 1, endOffset);
          char c = text.array[text.offset];
          SegmentCache.releaseSharedSegment(text);
          if (c == '\n') {
            return -1;
          }
          biasRet[0] = Position.Bias.Backward;
        } else {
          biasRet[0] = Position.Bias.Forward;
        }
        return pos;
      default:
        throw new IllegalArgumentException("Bad direction: " + direction);
    }
    return pos;
  }