예제 #1
1
  private void updateTemplateFromEditor(PrintfTemplate template) {
    ArrayList params = new ArrayList();
    String format = null;
    int text_length = editorPane.getDocument().getLength();
    try {
      format = editorPane.getDocument().getText(0, text_length);
    } catch (BadLocationException ex1) {
    }
    Element section_el = editorPane.getDocument().getDefaultRootElement();
    // Get number of paragraphs.
    int num_para = section_el.getElementCount();
    for (int p_count = 0; p_count < num_para; p_count++) {
      Element para_el = section_el.getElement(p_count);
      // Enumerate the content elements
      int num_cont = para_el.getElementCount();
      for (int c_count = 0; c_count < num_cont; c_count++) {
        Element content_el = para_el.getElement(c_count);
        AttributeSet attr = content_el.getAttributes();
        // Get the name of the style applied to this content element; may be null
        String sn = (String) attr.getAttribute(StyleConstants.NameAttribute);
        // Check if style name match
        if (sn != null && sn.startsWith("Parameter")) {
          // we extract the label.
          JLabel l = (JLabel) StyleConstants.getComponent(attr);
          if (l != null) {
            params.add(l.getName());
          }
        }
      }
    }

    template.setFormat(format);
    template.setTokens(params);
  }
예제 #2
0
  /**
   * Repaint the region of change covered by the given document event. Damages the line that begins
   * the range to cover the case when the insert/remove is only on one line. If lines are added or
   * removed, damages the whole view. The longest line is checked to see if it has changed.
   */
  protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f) {
    Component host = getContainer();
    updateMetrics();
    Element elem = getElement();
    DocumentEvent.ElementChange ec = changes.getChange(elem);
    Element[] added = (ec != null) ? ec.getChildrenAdded() : null;
    Element[] removed = (ec != null) ? ec.getChildrenRemoved() : null;
    if (((added != null) && (added.length > 0)) || ((removed != null) && (removed.length > 0))) {
      // lines were added or removed...
      if (added != null) {
        int addedAt = ec.getIndex(); // FIXME: Is this correct?????
        for (int i = 0; i < added.length; i++) possiblyUpdateLongLine(added[i], addedAt + i);
      }
      if (removed != null) {
        for (int i = 0; i < removed.length; i++) {
          if (removed[i] == longLine) {
            longLineWidth = -1; // Must do this!!
            calculateLongestLine();
            break;
          }
        }
      }
      preferenceChanged(null, true, true);
      host.repaint();
    }

    // This occurs when syntax highlighting only changes on lines
    // (i.e. beginning a multiline comment).
    else if (changes.getType() == DocumentEvent.EventType.CHANGE) {
      // System.err.println("Updating the damage due to a CHANGE event...");
      int startLine = changes.getOffset();
      int endLine = changes.getLength();
      damageLineRange(startLine, endLine, a, host);
    } else {
      Element map = getElement();
      int line = map.getElementIndex(changes.getOffset());
      damageLineRange(line, line, a, host);
      if (changes.getType() == DocumentEvent.EventType.INSERT) {
        // check to see if the line is longer than current
        // longest line.
        Element e = map.getElement(line);
        if (e == longLine) {
          // We must recalculate longest line's width here
          // because it has gotten longer.
          longLineWidth = getLineWidth(line);
          preferenceChanged(null, true, false);
        } else {
          // If long line gets updated, update the status bars too.
          if (possiblyUpdateLongLine(e, line)) preferenceChanged(null, true, false);
        }
      } else if (changes.getType() == DocumentEvent.EventType.REMOVE) {
        if (map.getElement(line) == longLine) {
          // removed from longest line... recalc
          longLineWidth = -1; // Must do this!
          calculateLongestLine();
          preferenceChanged(null, true, false);
        }
      }
    }
  }
예제 #3
0
  /** Returns the offset where the selection ends on the specified line. */
  public int getSelectionEnd(int line) {
    if (line == selectionEndLine) return selectionEnd;
    else if (rectSelect) {
      Element map = document.getDefaultRootElement();
      int end = selectionEnd - map.getElement(selectionEndLine).getStartOffset();

      Element lineElement = map.getElement(line);
      int lineStart = lineElement.getStartOffset();
      int lineEnd = lineElement.getEndOffset() - 1;
      return Math.min(lineEnd, lineStart + end);
    } else return getLineEndOffset(line) - 1;
  }
  /**
   * Paints the word-wrapped text.
   *
   * @param g The graphics context in which to paint.
   * @param a The shape (usually a rectangle) in which to paint.
   */
  public void paint(Graphics g, Shape a) {

    Rectangle alloc = (a instanceof Rectangle) ? (Rectangle) a : a.getBounds();
    tabBase = alloc.x;

    Graphics2D g2d = (Graphics2D) g;
    host = (RSyntaxTextArea) getContainer();
    int ascent = host.getMaxAscent();
    int fontHeight = host.getLineHeight();
    FoldManager fm = host.getFoldManager();
    TokenPainter painter = host.getTokenPainter();
    Element root = getElement();

    // Whether token styles should always be painted, even in selections
    int selStart = host.getSelectionStart();
    int selEnd = host.getSelectionEnd();
    boolean useSelectedTextColor = host.getUseSelectedTextColor();

    int n = getViewCount(); // Number of lines.
    int x = alloc.x + getLeftInset();
    tempRect.y = alloc.y + getTopInset();
    Rectangle clip = g.getClipBounds();
    for (int i = 0; i < n; i++) {

      tempRect.x = x + getOffset(X_AXIS, i);
      // tempRect.y = y + getOffset(Y_AXIS, i);
      tempRect.width = getSpan(X_AXIS, i);
      tempRect.height = getSpan(Y_AXIS, i);
      // System.err.println("For line " + i + ": tempRect==" + tempRect);

      if (tempRect.intersects(clip)) {
        Element lineElement = root.getElement(i);
        int startOffset = lineElement.getStartOffset();
        int endOffset = lineElement.getEndOffset() - 1; // Why always "-1"?
        View view = getView(i);
        if (!useSelectedTextColor
            || selStart == selEnd
            || (startOffset >= selEnd || endOffset < selStart)) {
          drawView(painter, g2d, alloc, view, fontHeight, tempRect.y + ascent);
        } else {
          // System.out.println("Drawing line with selection: " + i);
          drawViewWithSelection(
              painter, g2d, alloc, view, fontHeight, tempRect.y + ascent, selStart, selEnd);
        }
      }

      tempRect.y += tempRect.height;

      Fold possibleFold = fm.getFoldForLine(i);
      if (possibleFold != null && possibleFold.isCollapsed()) {
        i += possibleFold.getCollapsedLineCount();
        // Visible indicator of collapsed lines
        Color c = RSyntaxUtilities.getFoldedLineBottomColor(host);
        if (c != null) {
          g.setColor(c);
          g.drawLine(x, tempRect.y - 1, alloc.width, tempRect.y - 1);
        }
      }
    }
  }
예제 #5
0
  /*
   *	Get the line number to be drawn. The empty string will be returned
   *  when a line of text has wrapped.
   */
  protected String getTextLineNumber(int rowStartOffset) {
    Element root = component.getDocument().getDefaultRootElement();
    int index = root.getElementIndex(rowStartOffset);
    Element line = root.getElement(index);

    if (line.getStartOffset() == rowStartOffset) return String.valueOf(index + 1);
    else return "";
  }
  /**
   * Provides a mapping from the view coordinate space to the logical coordinate space of the model.
   *
   * @param fx the X coordinate &gt;= 0
   * @param fy the Y coordinate &gt;= 0
   * @param a the allocated region to render into
   * @return the location within the model that best represents the given point in the view &gt;= 0
   */
  @Override
  public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) {

    bias[0] = Position.Bias.Forward;

    Rectangle alloc = a.getBounds();
    RSyntaxDocument doc = (RSyntaxDocument) getDocument();
    int x = (int) fx;
    int y = (int) fy;

    // If they're asking about a view position above the area covered by
    // this view, then the position is assumed to be the starting position
    // of this view.
    if (y < alloc.y) {
      return getStartOffset();
    }

    // If they're asking about a position below this view, the position
    // is assumed to be the ending position of this view.
    else if (y > alloc.y + alloc.height) {
      return host.getLastVisibleOffset();
    }

    // They're asking about a position within the coverage of this view
    // vertically.  So, we figure out which line the point corresponds to.
    // If the line is greater than the number of lines contained, then
    // simply use the last line as it represents the last possible place
    // we can position to.
    else {

      Element map = doc.getDefaultRootElement();
      int lineIndex = Math.abs((y - alloc.y) / lineHeight); // metrics.getHeight() );
      FoldManager fm = host.getFoldManager();
      // System.out.print("--- " + lineIndex);
      lineIndex += fm.getHiddenLineCountAbove(lineIndex, true);
      // System.out.println(" => " + lineIndex);
      if (lineIndex >= map.getElementCount()) {
        return host.getLastVisibleOffset();
      }

      Element line = map.getElement(lineIndex);

      // If the point is to the left of the line...
      if (x < alloc.x) {
        return line.getStartOffset();
      } else if (x > alloc.x + alloc.width) {
        return line.getEndOffset() - 1;
      } else {
        // Determine the offset into the text
        int p0 = line.getStartOffset();
        Token tokenList = doc.getTokenListForLine(lineIndex);
        tabBase = alloc.x;
        int offs = tokenList.getListOffset((RSyntaxTextArea) getContainer(), this, tabBase, x);
        return offs != -1 ? offs : p0;
      }
    } // End of else.
  }
 /**
  * Loads all of the children to initialize the view. This is called by the <code>setParent</code>
  * method. Subclasses can re-implement this to initialize their child views in a different manner.
  * The default implementation creates a child view for each child element.
  *
  * @param f the view factory
  */
 protected void loadChildren(ViewFactory f) {
   Element e = getElement();
   int n = e.getElementCount();
   if (n > 0) {
     View[] added = new View[n];
     for (int i = 0; i < n; i++) added[i] = new WrappedLine(e.getElement(i));
     replace(0, 0, added);
   }
 }
예제 #8
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;
  }
예제 #9
0
  /** Returns the selected text, or null if no selection is active. */
  public final String getSelectedText() {
    if (selectionStart == selectionEnd) return null;

    if (rectSelect) {
      // Return each row of the selection on a new line

      Element map = document.getDefaultRootElement();

      int start = selectionStart - map.getElement(selectionStartLine).getStartOffset();
      int end = selectionEnd - map.getElement(selectionEndLine).getStartOffset();

      // Certain rectangles satisfy this condition...
      if (end < start) {
        int tmp = end;
        end = start;
        start = tmp;
      }

      StringBuffer buf = new StringBuffer();
      Segment seg = new Segment();

      for (int i = selectionStartLine; i <= selectionEndLine; i++) {
        Element lineElement = map.getElement(i);
        int lineStart = lineElement.getStartOffset();
        int lineEnd = lineElement.getEndOffset() - 1;
        int lineLen = lineEnd - lineStart;

        lineStart = Math.min(lineStart + start, lineEnd);
        lineLen = Math.min(end - start, lineEnd - lineStart);

        getText(lineStart, lineLen, seg);
        buf.append(seg.array, seg.offset, seg.count);

        if (i != selectionEndLine) buf.append('\n');
      }

      return buf.toString();
    } else {
      return getText(selectionStart, selectionEnd - selectionStart);
    }
  }
예제 #10
0
 public void caretUpdate(CaretEvent e) {
   // when the cursor moves on _textView
   // this method will be called. Then, we
   // must determine what the line number is
   // and update the line number view
   Element root = textView.getDocument().getDefaultRootElement();
   int line = root.getElementIndex(e.getDot());
   root = root.getElement(line);
   int col = root.getElementIndex(e.getDot());
   lineNumberView.setText(line + ":" + col);
   // if text is selected then enable copy and cut
   boolean isSelection = e.getDot() != e.getMark();
   copyAction.setEnabled(isSelection);
   cutAction.setEnabled(isSelection);
 }
 /**
  * Iterate over the lines represented by the child elements of the element this view represents,
  * looking for the line that is the longest. The <em>longLine</em> variable is updated to
  * represent the longest line contained. The <em>font</em> variable is updated to indicate the
  * font used to calculate the longest line.
  */
 void calculateLongestLine() {
   Component c = getContainer();
   font = c.getFont();
   metrics = c.getFontMetrics(font);
   tabSize = getTabSize() * metrics.charWidth(' ');
   Element lines = getElement();
   int n = lines.getElementCount();
   for (int i = 0; i < n; i++) {
     Element line = lines.getElement(i);
     float w = getLineWidth(i);
     if (w > longLineWidth) {
       longLineWidth = w;
       longLine = line;
     }
   }
 }
 /**
  * Loads all of the children to initialize the view. This is called by the {@link #setParent}
  * method. Subclasses can reimplement this to initialize their child views in a different manner.
  * The default implementation creates a child view for each child element.
  *
  * @param f the view factory
  * @see #setParent
  */
 protected void loadChildren(ViewFactory f) {
   if (f == null) {
     // No factory. This most likely indicates the parent view
     // has changed out from under us, bail!
     return;
   }
   Element e = getElement();
   int n = e.getElementCount();
   if (n > 0) {
     View[] added = new View[n];
     for (int i = 0; i < n; i++) {
       added[i] = f.create(e.getElement(i));
     }
     replace(0, 0, added);
   }
 }
예제 #13
0
 /**
  * Returns a token list for the specified segment of text representing the specified line number.
  * This method is basically a wrapper for <code>tokenMaker.getTokenList</code> that takes into
  * account the last token on the previous line to assure token accuracy.
  *
  * @param line The line number of <code>text</code> in the document, >= 0.
  * @return A token list representing the specified line.
  */
 public final Token getTokenListForLine(int line) {
   Element map = getDefaultRootElement();
   Element elem = map.getElement(line);
   int startOffset = elem.getStartOffset();
   // int endOffset = (line==map.getElementCount()-1 ? elem.getEndOffset() - 1:
   //									elem.getEndOffset() - 1);
   int endOffset = elem.getEndOffset() - 1; // Why always "-1"?
   try {
     getText(startOffset, endOffset - startOffset, s);
   } catch (BadLocationException ble) {
     ble.printStackTrace();
     return null;
   }
   int initialTokenType = line == 0 ? Token.NULL : getLastTokenTypeOnLine(line - 1);
   return tokenMaker.getTokenList(s, initialTokenType, startOffset);
 }
예제 #14
0
    private String addWhiteSpace(Document doc, int offset) throws BadLocationException {
      StringBuilder whiteSpace = new StringBuilder("\n");
      Element rootElement = doc.getDefaultRootElement();
      int line = rootElement.getElementIndex(offset);
      int i = rootElement.getElement(line).getStartOffset();

      while (true) {
        String temp = doc.getText(i, 1);

        if (temp.equals(" ") || temp.equals("\t")) {
          whiteSpace.append(temp);
          i++;
        } else break;
      }

      return whiteSpace.toString();
    }
예제 #15
0
  /**
   * Makes our private <code>Segment s</code> point to the text in our document referenced by the
   * specified element. Note that <code>line</code> MUST be a valid line number in the document.
   *
   * @param line The line number you want to get.
   */
  private final void setSharedSegment(int line) {

    Element map = getDefaultRootElement();
    // int numLines = map.getElementCount();

    Element element = map.getElement(line);
    if (element == null) throw new InternalError("Invalid line number: " + line);
    int startOffset = element.getStartOffset();
    // int endOffset = (line==numLines-1 ?
    //			element.getEndOffset()-1 : element.getEndOffset() - 1);
    int endOffset = element.getEndOffset() - 1; // Why always "-1"?
    try {
      getText(startOffset, endOffset - startOffset, s);
    } catch (BadLocationException ble) {
      throw new InternalError("Text range not in document: " + startOffset + "-" + endOffset);
    }
  }
  /**
   * Actually paints the text area. Only lines that have been damaged are repainted.
   *
   * @param g The graphics context with which to paint.
   * @param a The allocated region in which to render.
   */
  @Override
  public void paint(Graphics g, Shape a) {

    RSyntaxDocument document = (RSyntaxDocument) getDocument();

    Rectangle alloc = a.getBounds();

    tabBase = alloc.x;
    host = (RSyntaxTextArea) getContainer();

    Rectangle clip = g.getClipBounds();
    // An attempt to speed things up for files with long lines.  Note that
    // this will actually slow things down a bit for the common case of
    // regular-length lines, but it doesn't make a perceivable difference.
    clipStart = clip.x;
    clipEnd = clipStart + clip.width;

    lineHeight = host.getLineHeight();
    ascent = host.getMaxAscent(); // metrics.getAscent();
    int heightAbove = clip.y - alloc.y;
    int linesAbove = Math.max(0, heightAbove / lineHeight);

    FoldManager fm = host.getFoldManager();
    linesAbove += fm.getHiddenLineCountAbove(linesAbove, true);
    Rectangle lineArea = lineToRect(a, linesAbove);
    int y = lineArea.y + ascent;
    int x = lineArea.x;
    Element map = getElement();
    int lineCount = map.getElementCount();

    // Whether token styles should always be painted, even in selections
    int selStart = host.getSelectionStart();
    int selEnd = host.getSelectionEnd();

    RSyntaxTextAreaHighlighter h = (RSyntaxTextAreaHighlighter) host.getHighlighter();

    Graphics2D g2d = (Graphics2D) g;
    Token token;
    // System.err.println("Painting lines: " + linesAbove + " to " + (endLine-1));

    TokenPainter painter = host.getTokenPainter();
    int line = linesAbove;
    // int count = 0;
    while (y < clip.y + clip.height + ascent && line < lineCount) {

      Fold fold = fm.getFoldForLine(line);
      Element lineElement = map.getElement(line);
      int startOffset = lineElement.getStartOffset();
      // int endOffset = (line==lineCount ? lineElement.getEndOffset()-1 :
      //							lineElement.getEndOffset()-1);
      int endOffset = lineElement.getEndOffset() - 1; // Why always "-1"?
      h.paintLayeredHighlights(g2d, startOffset, endOffset, a, host, this);

      // Paint a line of text.
      token = document.getTokenListForLine(line);
      if (selStart == selEnd || startOffset >= selEnd || endOffset < selStart) {
        drawLine(painter, token, g2d, x, y, line);
      } else {
        // System.out.println("Drawing line with selection: " + line);
        drawLineWithSelection(painter, token, g2d, x, y, selStart, selEnd);
      }

      if (fold != null && fold.isCollapsed()) {

        // Visible indicator of collapsed lines
        Color c = RSyntaxUtilities.getFoldedLineBottomColor(host);
        if (c != null) {
          g.setColor(c);
          g.drawLine(x, y + lineHeight - ascent - 1, host.getWidth(), y + lineHeight - ascent - 1);
        }

        // Skip to next line to paint, taking extra care for lines with
        // block ends and begins together, e.g. "} else {"
        do {
          int hiddenLineCount = fold.getLineCount();
          if (hiddenLineCount == 0) {
            // Fold parser identified a zero-line fold region.
            // This is really a bug, but we'll be graceful here
            // and avoid an infinite loop.
            break;
          }
          line += hiddenLineCount;
          fold = fm.getFoldForLine(line);
        } while (fold != null && fold.isCollapsed());
      }

      y += lineHeight;
      line++;
      // count++;

    }

    // System.out.println("SyntaxView: lines painted=" + count);

  }
예제 #17
0
  /**
   * Replaces the selection with the specified text.
   *
   * @param selectedText The replacement text for the selection
   */
  public void setSelectedText(String selectedText) {
    if (!editable) {
      throw new InternalError("Text component" + " read only");
    }

    document.beginCompoundEdit();

    try {
      if (rectSelect) {
        Element map = document.getDefaultRootElement();

        int start = selectionStart - map.getElement(selectionStartLine).getStartOffset();
        int end = selectionEnd - map.getElement(selectionEndLine).getStartOffset();

        // Certain rectangles satisfy this condition...
        if (end < start) {
          int tmp = end;
          end = start;
          start = tmp;
        }

        int lastNewline = 0;
        int currNewline = 0;

        for (int i = selectionStartLine; i <= selectionEndLine; i++) {
          Element lineElement = map.getElement(i);
          int lineStart = lineElement.getStartOffset();
          int lineEnd = lineElement.getEndOffset() - 1;
          int rectStart = Math.min(lineEnd, lineStart + start);

          document.remove(rectStart, Math.min(lineEnd - rectStart, end - start));

          if (selectedText == null) continue;

          currNewline = selectedText.indexOf('\n', lastNewline);
          if (currNewline == -1) currNewline = selectedText.length();

          document.insertString(rectStart, selectedText.substring(lastNewline, currNewline), null);

          lastNewline = Math.min(selectedText.length(), currNewline + 1);
        }

        if (selectedText != null && currNewline != selectedText.length()) {
          int offset = map.getElement(selectionEndLine).getEndOffset() - 1;
          document.insertString(offset, "\n", null);
          document.insertString(offset + 1, selectedText.substring(currNewline + 1), null);
        }
      } else {
        document.remove(selectionStart, selectionEnd - selectionStart);
        if (selectedText != null) {
          document.insertString(selectionStart, selectedText, null);
        }
      }
    } catch (BadLocationException bl) {
      bl.printStackTrace();
      throw new InternalError("Cannot replace" + " selection");
    }
    // No matter what happends... stops us from leaving document
    // in a bad state
    finally {
      document.endCompoundEdit();
    }

    setCaretPosition(selectionEnd);
  }