/** * Renders using the given rendering surface and area on that surface. * * @param g the rendering surface to use * @param allocation the allocated region to render into * @see View#paint */ public void paint(Graphics g, Shape allocation) { super.paint(g, allocation); Rectangle alloc = allocation.getBounds(); Rectangle clip = g.getClipBounds(); // Since listPainter paints in the insets we have to check for the // case where the child is not painted because the paint region is // to the left of the child. This assumes the ListPainter paints in // the left margin. if ((clip.x + clip.width) < (alloc.x + getLeftInset())) { Rectangle childRect = alloc; alloc = getInsideAllocation(allocation); int n = getViewCount(); int endY = clip.y + clip.height; for (int i = 0; i < n; i++) { childRect.setBounds(alloc); childAllocation(i, childRect); if (childRect.y < endY) { if ((childRect.y + childRect.height) >= clip.y) { listPainter.paint( g, childRect.x, childRect.y, childRect.width, childRect.height, this, i); } } else { break; } } } }
// ------------------------------ public void scrollToCaret() { // not called - fixed with putting visible scrollbars on JScrollPane // Rectangle rect1 = scroller1.getViewport().getViewRect(); double x1 = rect1.getX(); double y1 = rect1.getY(); double r1height = rect1.getHeight(); double r1width = rect1.getWidth(); Caret caret1 = editor1.getCaret(); Point pt2 = caret1.getMagicCaretPosition(); // the end of the string double x2 = pt2.getX(); double y2 = pt2.getY(); if (((x2 > x1) && (x2 < (x1 + r1width))) && ((y2 > y1) && (y2 < (y1 + r1height)))) { // inview } else { double newheight = r1height / 2; double newwidth = r1width / 2; double x3 = pt2.getX() - newwidth; double y3 = pt2.getY() - newheight; if (x3 < 0) x3 = 0; if (y3 < 0) y3 = 0; Rectangle rect3 = new Rectangle((int) x3, (int) y3, (int) newwidth, (int) newheight); editor1.scrollRectToVisible(rect3); } } // end scrollToCaret
/** * Repaint the given line range. * * @param line0 The starting line number to repaint. This must be a valid line number in the * model. * @param line1 The ending line number to repaint. This must be a valid line number in the model. * @param a The region allocated for the view to render into. * @param host The component hosting the view (used to call repaint). */ protected void damageLineRange(int line0, int line1, Shape a, Component host) { if (a != null) { Rectangle area0 = lineToRect(a, line0); Rectangle area1 = lineToRect(a, line1); if ((area0 != null) && (area1 != null)) { Rectangle dmg = area0.union(area1); // damage. host.repaint(dmg.x, dmg.y, dmg.width, dmg.height); } else host.repaint(); } }
/** * 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); }
protected Rectangle getVisibleEditorRect() { final Rectangle rect = super.getVisibleEditorRect(); if (rect == null) return null; if (!getComponent().isOpaque()) { rect.y -= 3; rect.height += 6; } return rect; }
/** * 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; }
public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException { int p0 = getStartOffset(); int p1 = getEndOffset(); if ((pos >= p0) && (pos <= p1)) { Rectangle r = a.getBounds(); if (pos == p1) { r.x += r.width; } r.width = 0; return r; } throw new BadLocationException(pos + " not in range " + p0 + "," + p1, pos); }
/** [Internal] */ public void paintComponent(Graphics g) { boolean opq = true; if (theOpaque != null) opq = theOpaque; super.setOpaque(opq); // if(theBackground!=null)super.setBackground(theBackground); super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; Rectangle rt = getBounds(); rt.x = 0; rt.y = 0; doBuffer(g2, opq, rt); chkFPS(); }
/** * Writes the <code>shape</code>, <code>coords</code>, <code>href</code>, * <code>nohref</code> Attribute for the specified figure and ellipse. * * @return Returns true, if the circle is inside of the image bounds. */ private boolean writeCircleAttributes(IXMLElement elem, SVGFigure f, Ellipse2D.Double ellipse) { AffineTransform t = TRANSFORM.getClone(f); if (t == null) { t = drawingTransform; } else { t.preConcatenate(drawingTransform); } if ((t.getType() & (AffineTransform.TYPE_UNIFORM_SCALE | AffineTransform.TYPE_TRANSLATION)) == t.getType() && ellipse.width == ellipse.height ) { Point2D.Double start = new Point2D.Double(ellipse.x, ellipse.y); Point2D.Double end = new Point2D.Double(ellipse.x + ellipse.width, ellipse.y + ellipse.height); t.transform(start, start); t.transform(end, end); ellipse.x = Math.min(start.x, end.x); ellipse.y = Math.min(start.y, end.y); ellipse.width = Math.abs(start.x - end.x); ellipse.height = Math.abs(start.y - end.y); elem.setAttribute("shape", "circle"); elem.setAttribute("coords", (int) (ellipse.x + ellipse.width / 2d)+","+ (int) (ellipse.y + ellipse.height / 2d)+","+ (int) (ellipse.width / 2d) ); writeHrefAttribute(elem, f); return bounds.intersects(ellipse.getBounds()); } else { return writePolyAttributes(elem, f, (Shape) ellipse); } }
/** * 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(); }
/** * Provides a mapping, for a given region, from the document model coordinate space to the view * coordinate space. The specified region is created as a union of the first and last character * positions. * * <p>This is implemented to subtract the width of the second character, as this view's <code> * modelToView</code> actually returns the width of the character instead of "1" or "0" like the * View implementations in <code>javax.swing.text</code>. Thus, if we don't override this method, * the <code>View</code> implementation will return one character's width too much for its * consumers (implementations of <code>javax.swing.text.Highlighter</code>). * * @param p0 the position of the first character (>=0) * @param b0 The bias of the first character position, toward the previous character or the next * character represented by the offset, in case the position is a boundary of two views; * <code>b0</code> will have one of these values: * <ul> * <li><code>Position.Bias.Forward</code> * <li><code>Position.Bias.Backward</code> * </ul> * * @param p1 the position of the last character (>=0) * @param b1 the bias for the second character position, defined one of the legal values shown * above * @param a the area of the view, which encompasses the requested region * @return the bounding box which is a union of the region specified by the first and last * character positions * @exception BadLocationException if the given position does not represent a valid location in * the associated document * @exception IllegalArgumentException if <code>b0</code> or <code>b1</code> are not one of the * legal <code>Position.Bias</code> values listed above * @see View#viewToModel */ @Override public Shape modelToView(int p0, Position.Bias b0, int p1, Position.Bias b1, Shape a) throws BadLocationException { Shape s0 = modelToView(p0, a, b0); Shape s1; if (p1 == getEndOffset()) { try { s1 = modelToView(p1, a, b1); } catch (BadLocationException ble) { s1 = null; } if (s1 == null) { // Assume extends left to right. Rectangle alloc = (a instanceof Rectangle) ? (Rectangle) a : a.getBounds(); s1 = new Rectangle(alloc.x + alloc.width - 1, alloc.y, 1, alloc.height); } } else { s1 = modelToView(p1, a, b1); } Rectangle r0 = s0 instanceof Rectangle ? (Rectangle) s0 : s0.getBounds(); Rectangle r1 = s1 instanceof Rectangle ? (Rectangle) s1 : s1.getBounds(); if (r0.y != r1.y) { // If it spans lines, force it to be the width of the view. Rectangle alloc = (a instanceof Rectangle) ? (Rectangle) a : a.getBounds(); r0.x = alloc.x; r0.width = alloc.width; } r0.add(r1); // The next line is the only difference between this method and // View's implementation. We're subtracting the width of the second // character. This is because this method is used by Highlighter // implementations to get the area to "highlight", and if we don't do // this, one character too many is highlighted thanks to our // modelToView() implementation returning the actual width of the // character requested! if (p1 > p0) { r0.width -= r1.width; } return r0; }
/** * 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); } } } }
/** * Writes the <code>shape</code>, <code>coords</code>, <code>href</code>, * <code>nohref</code> Attribute for the specified figure and rectangle. * * @return Returns true, if the rect is inside of the image bounds. */ private boolean writeRectAttributes(IXMLElement elem, SVGFigure f, Rectangle2D.Double rect) { AffineTransform t = TRANSFORM.getClone(f); if (t == null) { t = drawingTransform; } else { t.preConcatenate(drawingTransform); } if ((t.getType() & (AffineTransform.TYPE_UNIFORM_SCALE | AffineTransform.TYPE_TRANSLATION)) == t.getType() ) { Point2D.Double start = new Point2D.Double(rect.x, rect.y); Point2D.Double end = new Point2D.Double(rect.x + rect.width, rect.y + rect.height); t.transform(start, start); t.transform(end, end); Rectangle r = new Rectangle( (int) Math.min(start.x, end.x), (int) Math.min(start.y, end.y), (int) Math.abs(start.x - end.x), (int) Math.abs(start.y - end.y) ); elem.setAttribute("shape", "rect"); elem.setAttribute("coords", r.x + ","+ r.y + ","+ (r.x + r.width) + ","+ (r.y + r.height) ); writeHrefAttribute(elem, f); return bounds.intersects(r); } else { return writePolyAttributes(elem, f, (Shape) 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); } } } }
@Override protected void paintText( Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected) { g.setFont(font); int titleWidth = SwingUtilities.computeStringWidth(metrics, title); int preferredWidth = 0; if (isOneActionButtonEnabled()) { preferredWidth = calculateTabWidth(tabPlacement, tabIndex, metrics) - WIDTHDELTA - 15; if (isCloseEnabled()) preferredWidth -= BUTTONSIZE; if (isMaxEnabled()) preferredWidth -= BUTTONSIZE; } else { preferredWidth = titleWidth; } while (titleWidth > preferredWidth) { if (title.endsWith("...")) title = title.substring(0, title.indexOf("...") - 1).concat("..."); else title = title.substring(0, title.length() - 4).concat("..."); titleWidth = SwingUtilities.computeStringWidth(metrics, title); } textRect.width = titleWidth; View v = getTextViewForTab(tabIndex); if (v != null) { // html v.paint(g, textRect); } else { // plain text int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) { if (isSelected) g.setColor(TAB_SELECTED_FOREGROUND_COLOR); else { if (this.isTabHighlighted(tabIndex)) { g.setColor(TAB_HIGHLIGHT_FOREGROUND_COLOR); } else g.setColor(tabPane.getForegroundAt(tabIndex)); } BasicGraphicsUtils.drawString( g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); } else { // tab disabled g.setColor(tabPane.getBackgroundAt(tabIndex).brighter()); BasicGraphicsUtils.drawStringUnderlineCharAt( g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent()); g.setColor(tabPane.getBackgroundAt(tabIndex).darker()); BasicGraphicsUtils.drawStringUnderlineCharAt( g, title, mnemIndex, textRect.x - 1, textRect.y + metrics.getAscent() - 1); } } }
// Graphics2D g=getG();return g==null?null:g.getClipBounds();} public Rectangle getClipBounds(Rectangle r) { Shape s = bufferClip(); if (s == null) return null; r.setBounds(bufferClip().getBounds()); return r; }
/** * 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); }