/** * Overridden to show the content of a collapsed fold on mouse-overs. * * @param e The mouse location. */ public String getToolTipText(MouseEvent e) { String text = null; RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; if (rsta.isCodeFoldingEnabled()) { FoldManager fm = rsta.getFoldManager(); int pos = rsta.viewToModel(new Point(0, e.getY())); if (pos >= 0) { // Not -1 int line = 0; try { line = rsta.getLineOfOffset(pos); } catch (BadLocationException ble) { ble.printStackTrace(); // Never happens return null; } Fold fold = fm.getFoldForLine(line); if (fold != null && fold.isCollapsed()) { int endLine = fold.getEndLine(); if (fold.getLineCount() > 25) { // Not too big endLine = fold.getStartLine() + 25; } StringBuffer sb = new StringBuffer("<html><nobr>"); while (line <= endLine && line < rsta.getLineCount()) { // Sanity Token t = rsta.getTokenListForLine(line); while (t != null && t.isPaintable()) { t.appendHTMLRepresentation(sb, rsta, true, true); t = t.getNextToken(); } sb.append("<br>"); line++; } text = sb.toString(); } } } return text; }
/** * Paints folding icons when line wrapping is enabled. * * @param g The graphics context. */ private void paintComponentWrapped(Graphics g) { // The variables we use are as follows: // - visibleRect is the "visible" area of the text area; e.g. // [0,100, 300,100+(lineCount*cellHeight)-1]. // actualTop.y is the topmost-pixel in the first logical line we // paint. Note that we may well not paint this part of the logical // line, as it may be broken into many physical lines, with the first // few physical lines scrolled past. Note also that this is NOT the // visible rect of this line number list; this line number list has // visible rect == [0,0, insets.left-1,visibleRect.height-1]. // - offset (<=0) is the y-coordinate at which we begin painting when // we begin painting with the first logical line. This can be // negative, signifying that we've scrolled past the actual topmost // part of this line. // The algorithm is as follows: // - Get the starting y-coordinate at which to paint. This may be // above the first visible y-coordinate as we're in line-wrapping // mode, but we always paint entire logical lines. // - Paint that line's indicator, if appropriate. Increment y to be // just below the are we just painted (i.e., the beginning of the // next logical line's view area). // - Get the ending visual position for that line. We can now loop // back, paint this line, and continue until our y-coordinate is // past the last visible y-value. // We avoid using modelToView/viewToModel where possible, as these // methods trigger a parsing of the line into syntax tokens, which is // costly. It's cheaper to just grab the child views' bounds. // Some variables we'll be using. int width = getWidth(); RTextAreaUI ui = (RTextAreaUI) textArea.getUI(); View v = ui.getRootView(textArea).getView(0); Document doc = textArea.getDocument(); Element root = doc.getDefaultRootElement(); int topPosition = textArea.viewToModel(new Point(visibleRect.x, visibleRect.y)); int topLine = root.getElementIndex(topPosition); int cellHeight = textArea.getLineHeight(); FoldManager fm = ((RSyntaxTextArea) textArea).getFoldManager(); // Compute the y at which to begin painting text, taking into account // that 1 logical line => at least 1 physical line, so it may be that // y<0. The computed y-value is the y-value of the top of the first // (possibly) partially-visible view. Rectangle visibleEditorRect = ui.getVisibleEditorRect(); Rectangle r = LineNumberList.getChildViewBounds(v, topLine, visibleEditorRect); int y = r.y; y += (cellHeight - collapsedFoldIcon.getIconHeight()) / 2; int visibleBottom = visibleRect.y + visibleRect.height; int x = width - 10; int line = topLine; boolean paintingOutlineLine = foldWithOutlineShowing != null && foldWithOutlineShowing.containsLine(line); int lineCount = root.getElementCount(); while (y < visibleBottom && line < lineCount) { int curLineH = LineNumberList.getChildViewBounds(v, line, visibleEditorRect).height; if (paintingOutlineLine) { g.setColor(getForeground()); int w2 = width / 2; if (line == foldWithOutlineShowing.getEndLine()) { int y2 = y + curLineH - cellHeight / 2; g.drawLine(w2, y, w2, y2); g.drawLine(w2, y2, width - 2, y2); paintingOutlineLine = false; } else { g.drawLine(w2, y, w2, y + curLineH); } } Fold fold = fm.getFoldForLine(line); if (fold != null) { if (fold == foldWithOutlineShowing && !fold.isCollapsed()) { g.setColor(getForeground()); int w2 = width / 2; g.drawLine(w2, y + cellHeight / 2, w2, y + curLineH); paintingOutlineLine = true; } if (fold.isCollapsed()) { collapsedFoldIcon.paintIcon(this, g, x, y); y += LineNumberList.getChildViewBounds(v, line, visibleEditorRect).height; line += fold.getLineCount() + 1; } else { expandedFoldIcon.paintIcon(this, g, x, y); y += curLineH; line++; } } else { y += curLineH; line++; } } }
protected void paintComponent(Graphics g) { if (textArea == null) { return; } visibleRect = g.getClipBounds(visibleRect); if (visibleRect == null) { // ??? visibleRect = getVisibleRect(); } // System.out.println("IconRowHeader repainting: " + visibleRect); if (visibleRect == null) { return; } Color bg = getBackground(); if (getGutter() != null) { // Should always be true bg = getGutter().getBackground(); } g.setColor(bg); g.fillRect(0, visibleRect.y, getWidth(), visibleRect.height); RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; if (!rsta.isCodeFoldingEnabled()) { return; // We should be hidden in this case, but still... } if (textArea.getLineWrap()) { paintComponentWrapped(g); return; } // Get where to start painting (top of the row). // We need to be "scrolled up" up just enough for the missing part of // the first line. int cellHeight = textArea.getLineHeight(); int topLine = visibleRect.y / cellHeight; int y = topLine * cellHeight + (cellHeight - collapsedFoldIcon.getIconHeight()) / 2; textAreaInsets = textArea.getInsets(textAreaInsets); if (textAreaInsets != null) { y += textAreaInsets.top; } // Get the first and last lines to paint. FoldManager fm = rsta.getFoldManager(); topLine += fm.getHiddenLineCountAbove(topLine, true); int width = getWidth(); int x = width - 10; int line = topLine; boolean paintingOutlineLine = foldWithOutlineShowing != null && foldWithOutlineShowing.containsLine(line); while (y < visibleRect.y + visibleRect.height) { if (paintingOutlineLine) { g.setColor(getForeground()); int w2 = width / 2; if (line == foldWithOutlineShowing.getEndLine()) { int y2 = y + cellHeight / 2; g.drawLine(w2, y, w2, y2); g.drawLine(w2, y2, width - 2, y2); paintingOutlineLine = false; } else { g.drawLine(w2, y, w2, y + cellHeight); } } Fold fold = fm.getFoldForLine(line); if (fold != null) { if (fold == foldWithOutlineShowing && !fold.isCollapsed()) { g.setColor(getForeground()); int w2 = width / 2; g.drawLine(w2, y + cellHeight / 2, w2, y + cellHeight); paintingOutlineLine = true; } if (fold.isCollapsed()) { collapsedFoldIcon.paintIcon(this, g, x, y); // Skip to next line to paint, taking extra care for lines with // block ends and begins together, e.g. "} else {" do { line += fold.getLineCount(); fold = fm.getFoldForLine(line); } while (fold != null && fold.isCollapsed()); } else { expandedFoldIcon.paintIcon(this, g, x, y); } } line++; y += cellHeight; } }