/** * Damages the area surrounding the caret to cause it to be repainted in a new location. If * paint() is reimplemented, this method should also be reimplemented. This method should update * the caret bounds (x, y, width, and height). * * @param r the current location of the caret * @see #paint */ @Override protected synchronized void damage(final Rectangle r) { if (r == null || fPainting) return; x = r.x - 4; y = r.y; width = 10; height = r.height; // Don't damage the border area. We can't paint a partial border, so get the // intersection of the caret rectangle and the component less the border, if any. final Rectangle caretRect = new Rectangle(x, y, width, height); final Border border = getComponent().getBorder(); if (border != null) { final Rectangle alloc = getComponent().getBounds(); alloc.x = alloc.y = 0; final Insets borderInsets = border.getBorderInsets(getComponent()); alloc.x += borderInsets.left; alloc.y += borderInsets.top; alloc.width -= borderInsets.left + borderInsets.right; alloc.height -= borderInsets.top + borderInsets.bottom; Rectangle2D.intersect(caretRect, alloc, caretRect); } x = caretRect.x; y = caretRect.y; width = Math.max(caretRect.width, 1); height = Math.max(caretRect.height, 1); repaint(); }
/** * 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); } } } }
/** * Provides a mapping from the document model coordinate space to the coordinate space of the * view mapped to it. * * @param pos the position to convert * @param a the allocated region to render into * @return the bounding box of the given position is returned * @exception BadLocationException if the given position does not represent a valid location in * the associated document. */ @Override public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException { // System.err.println("--- begin modelToView ---"); Rectangle alloc = a.getBounds(); RSyntaxTextArea textArea = (RSyntaxTextArea) getContainer(); alloc.height = textArea.getLineHeight(); // metrics.getHeight(); alloc.width = 1; int p0 = getStartOffset(); int p1 = getEndOffset(); int testP = (b == Position.Bias.Forward) ? pos : Math.max(p0, pos - 1); // Get the token list for this line so we don't have to keep // recomputing it if this logical line spans multiple physical // lines. RSyntaxDocument doc = (RSyntaxDocument) getDocument(); Element map = doc.getDefaultRootElement(); int line = map.getElementIndex(p0); Token tokenList = doc.getTokenListForLine(line); float x0 = alloc.x; // 0; while (p0 < p1) { TokenSubList subList = TokenUtils.getSubTokenList( tokenList, p0, WrappedSyntaxView.this, textArea, x0, lineCountTempToken); x0 = subList != null ? subList.x : x0; tokenList = subList != null ? subList.tokenList : null; int p = calculateBreakPosition(p0, tokenList, x0); if ((pos >= p0) && (testP < p)) { // pos < p)) { // it's in this line alloc = RSyntaxUtilities.getLineWidthUpTo( textArea, s, p0, pos, WrappedSyntaxView.this, alloc, alloc.x); // System.err.println("--- end modelToView ---"); return alloc; } // if (p == p1 && pos == p1) { if (p == p1 - 1 && pos == p1 - 1) { // Wants end. if (pos > p0) { alloc = RSyntaxUtilities.getLineWidthUpTo( textArea, s, p0, pos, WrappedSyntaxView.this, alloc, alloc.x); } // System.err.println("--- end modelToView ---"); return alloc; } p0 = (p == p0) ? p1 : p; // System.err.println("... ... Incrementing y"); alloc.y += alloc.height; } throw new BadLocationException(null, pos); }
/** * Sets the allocation rectangle for a given line's view, but sets the y value to the passed-in * value. This should be used instead of {@link #childAllocation(int, Rectangle)} since it allows * you to account for hidden lines in collapsed fold regions. * * @param line * @param y * @param alloc */ private void childAllocation2(int line, int y, Rectangle alloc) { alloc.x += getOffset(X_AXIS, line); alloc.y += y; alloc.width = getSpan(X_AXIS, line); alloc.height = getSpan(Y_AXIS, line); // FIXME: This is required due to a bug that I can't track down. The // top margin is being added twice somewhere in wrapped views, so we // have to adjust for it here. alloc.y -= host.getMargin().top; }
protected Rectangle getVisibleEditorRect() { final Rectangle rect = super.getVisibleEditorRect(); if (rect == null) return null; if (!getComponent().isOpaque()) { rect.y -= 3; rect.height += 6; } return rect; }
/** * 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(); 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)) { View view = getView(i); drawView(g2d, alloc, view, fontHeight, tempRect.y + ascent); } 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); } } } }
/** * Provides a mapping from the view coordinate space to the logical coordinate space of the * model. * * @param fx the X coordinate * @param fy the Y coordinate * @param a the allocated region to render into * @return the location within the model that best represents the given point in the view * @see View#viewToModel */ @Override public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) { // PENDING(prinz) implement bias properly bias[0] = Position.Bias.Forward; Rectangle alloc = (Rectangle) a; RSyntaxDocument doc = (RSyntaxDocument) getDocument(); int x = (int) fx; int y = (int) fy; if (y < alloc.y) { // above the area covered by this icon, so the the position // is assumed to be the start of the coverage for this view. return getStartOffset(); } else if (y > alloc.y + alloc.height) { // below the area covered by this icon, so the the position // is assumed to be the end of the coverage for this view. return getEndOffset() - 1; } else { // positioned 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. RSyntaxTextArea textArea = (RSyntaxTextArea) getContainer(); alloc.height = textArea.getLineHeight(); int p1 = getEndOffset(); // Get the token list for this line so we don't have to keep // recomputing it if this logical line spans multiple // physical lines. Element map = doc.getDefaultRootElement(); int p0 = getStartOffset(); int line = map.getElementIndex(p0); Token tlist = doc.getTokenListForLine(line); // Look at each physical line-chunk of this logical line. while (p0 < p1) { // We can always use alloc.x since we always break // lines so they start at the beginning of a physical // line. TokenSubList subList = TokenUtils.getSubTokenList( tlist, p0, WrappedSyntaxView.this, textArea, alloc.x, lineCountTempToken); tlist = subList != null ? subList.tokenList : null; int p = calculateBreakPosition(p0, tlist, alloc.x); // If desired view position is in this physical chunk. if ((y >= alloc.y) && (y < (alloc.y + alloc.height))) { // Point is to the left of the line if (x < alloc.x) { return p0; } // Point is to the right of the line else if (x > alloc.x + alloc.width) { return p - 1; } // Point is in this physical line! else { // Start at alloc.x since this chunk starts // at the beginning of a physical line. int n = tlist.getListOffset(textArea, WrappedSyntaxView.this, alloc.x, x); // NOTE: We needed to add the max() with // p0 as getTokenListForLine returns -1 // for empty lines (just a null token). // How did this work before? // FIXME: Have null tokens have their // offset but a -1 length. return Math.max(Math.min(n, p1 - 1), p0); } // End of else. } // End of if ((y>=alloc.y) && ... p0 = (p == p0) ? p1 : p; alloc.y += alloc.height; } // End of while (p0<p1). return getEndOffset() - 1; } // End of else. }
/** * Sets the allocation rectangle for a given line's view, but sets the y value to the passed-in * value. This should be used instead of {@link #childAllocation(int, Rectangle)} since it allows * you to account for hidden lines in collapsed fold regions. * * @param line * @param y * @param alloc */ private void childAllocation2(int line, int y, Rectangle alloc) { alloc.x += getOffset(X_AXIS, line); alloc.y += y; alloc.width = getSpan(X_AXIS, line); alloc.height = getSpan(Y_AXIS, line); }