Пример #1
0
  /**
   * Provides a way to determine the next visually represented model location at which 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 pos the position to convert >= 0
   * @param a the allocated region in which to render
   * @param direction the direction from the current position that can be thought of as the arrow
   *     keys typically found on a keyboard. This will be one of the following values:
   *     <ul>
   *       <li>SwingConstants.WEST
   *       <li>SwingConstants.EAST
   *       <li>SwingConstants.NORTH
   *       <li>SwingConstants.SOUTH
   *     </ul>
   *
   * @return the location within the model that best represents the next location visual position
   * @exception BadLocationException
   * @exception IllegalArgumentException if <code>direction</code> doesn't have one of the legal
   *     values above
   */
  public int getNextVisualPositionFrom(
      int pos, Position.Bias b, Shape a, int direction, Position.Bias[] biasRet)
      throws BadLocationException {

    biasRet[0] = Position.Bias.Forward;
    switch (direction) {
      case NORTH:
      case SOUTH:
        {
          if (pos == -1) {
            pos = (direction == NORTH) ? Math.max(0, getEndOffset() - 1) : getStartOffset();
            break;
          }
          JTextComponent target = (JTextComponent) getContainer();
          Caret c = (target != null) ? target.getCaret() : null;
          // YECK! Ideally, the x location from the magic caret position
          // would be passed in.
          Point mcp;
          if (c != null) {
            mcp = c.getMagicCaretPosition();
          } else {
            mcp = null;
          }
          int x;
          if (mcp == null) {
            Rectangle loc = target.modelToView(pos);
            x = (loc == null) ? 0 : loc.x;
          } else {
            x = mcp.x;
          }
          if (direction == NORTH) {
            pos = Utilities.getPositionAbove(target, pos, x);
          } else {
            pos = Utilities.getPositionBelow(target, pos, x);
          }
        }
        break;
      case WEST:
        if (pos == -1) {
          pos = Math.max(0, getEndOffset() - 1);
        } else {
          pos = Math.max(0, pos - 1);
        }
        break;
      case EAST:
        if (pos == -1) {
          pos = getStartOffset();
        } else {
          pos = Math.min(pos + 1, getDocument().getLength());
        }
        break;
      default:
        throw new IllegalArgumentException("Bad direction: " + direction);
    }
    return pos;
  }
Пример #2
0
  /*
   *  Determine the Y offset for the current row
   */
  private int getOffsetY(int rowStartOffset, FontMetrics fontMetrics) throws BadLocationException {
    //  Get the bounding rectangle of the row

    Rectangle r = component.modelToView(rowStartOffset);
    int lineHeight = fontMetrics.getHeight();
    int y = r.y + r.height;
    int descent = 0;

    //  The text needs to be positioned above the bottom of the bounding
    //  rectangle based on the descent of the font(s) contained on the row.
    if (r.height == lineHeight) {
      // default font is being used
      descent = fontMetrics.getDescent();
    } else {
      // We need to check all the attributes for font changes
      if (fonts == null) {
        fonts = new HashMap<String, FontMetrics>();
      }

      Element root = component.getDocument().getDefaultRootElement();
      int index = root.getElementIndex(rowStartOffset);
      Element line = root.getElement(index);

      for (int i = 0; i < line.getElementCount(); i++) {
        Element child = line.getElement(i);
        AttributeSet as = child.getAttributes();
        String fontFamily = (String) as.getAttribute(StyleConstants.FontFamily);
        Integer fontSize = (Integer) as.getAttribute(StyleConstants.FontSize);
        String key = fontFamily + fontSize;

        FontMetrics fm = fonts.get(key);

        if (fm == null) {
          Font font = new Font(fontFamily, Font.PLAIN, fontSize);
          fm = component.getFontMetrics(font);
          fonts.put(key, fm);
        }

        descent = Math.max(descent, fm.getDescent());
      }
    }

    return y - descent;
  }
Пример #3
0
  /*
   *  A document change may affect the number of displayed lines of text.
   *  Therefore the lines numbers will also change.
   */
  private void documentChanged() {
    //  View of the component has not been updated at the time
    //  the DocumentEvent is fired

    SwingUtilities.invokeLater(
        () -> {
          try {
            int endPos = component.getDocument().getLength();
            Rectangle rect = component.modelToView(endPos);

            if (rect != null && rect.y != lastHeight) {
              setPreferredWidth();
              repaint();
              lastHeight = rect.y;
            }
          } catch (BadLocationException ex) {
            /* nothing to do */
          }
        });
  }
Пример #4
0
    @Override
    public void actionPerformed(ActionEvent e) {
      JTextComponent textArea = (JTextComponent) e.getSource();

      Caret caret = textArea.getCaret();
      int dot = caret.getDot();

      /*
       * Move to the beginning/end of selection on a "non-shifted"
       * left- or right-keypress.  We shouldn't have to worry about
       * navigation filters as, if one is being used, it let us get
       * to that position before.
       */
      if (!select) {
        switch (direction) {
          case SwingConstants.EAST:
            int mark = caret.getMark();
            if (dot != mark) {
              caret.setDot(Math.max(dot, mark));
              return;
            }
            break;
          case SwingConstants.WEST:
            mark = caret.getMark();
            if (dot != mark) {
              caret.setDot(Math.min(dot, mark));
              return;
            }
            break;
          default:
        }
      }

      Position.Bias[] bias = new Position.Bias[1];
      Point magicPosition = caret.getMagicCaretPosition();

      try {

        if (magicPosition == null
            && (direction == SwingConstants.NORTH || direction == SwingConstants.SOUTH)) {
          Rectangle r = textArea.modelToView(dot);
          magicPosition = new Point(r.x, r.y);
        }

        NavigationFilter filter = textArea.getNavigationFilter();

        if (filter != null) {
          dot =
              filter.getNextVisualPositionFrom(
                  textArea, dot, Position.Bias.Forward, direction, bias);
        } else {
          if (direction == SwingConstants.NORTH || direction == SwingConstants.SOUTH) {
            dot = getNSVisualPosition((EditorPane) textArea, dot, direction);
          } else {
            dot =
                textArea
                    .getUI()
                    .getNextVisualPositionFrom(
                        textArea, dot, Position.Bias.Forward, direction, bias);
          }
        }
        if (select) {
          caret.moveDot(dot);
        } else {
          caret.setDot(dot);
        }

        if (magicPosition != null
            && (direction == SwingConstants.NORTH || direction == SwingConstants.SOUTH)) {
          caret.setMagicCaretPosition(magicPosition);
        }

      } catch (BadLocationException ble) {
        Debug.error(me + "Problem while trying to move caret\n%s", ble.getMessage());
      }
    }