private Fold findOpenFoldClosestTo(Point p) { Fold fold = null; RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; if (rsta.isCodeFoldingEnabled()) { // Should always be true int offs = rsta.viewToModel(p); // TODO: Optimize me if (offs > -1) { try { int line = rsta.getLineOfOffset(offs); int origLine = line; FoldManager fm = rsta.getFoldManager(); do { fold = fm.getFoldForLine(line); } while (fold == null && line-- >= 0); if (fold != null && !fold.containsOrStartsOnLine(origLine)) { // Found closest fold, but doesn't actually contain line fold = null; } } catch (BadLocationException ble) { ble.printStackTrace(); // Never happens } } } return fold; }
/** * 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; }
public void mouseClicked(MouseEvent e) { // // TODO: Implement code folding with word wrap enabled // if (textArea.getLineWrap()) { // UIManager.getLookAndFeel().provideErrorFeedback(textArea); // return; // } Point p = e.getPoint(); int line = rowAtPoint(p); RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; FoldManager fm = rsta.getFoldManager(); Fold fold = fm.getFoldForLine(line); if (fold != null) { fold.toggleCollapsedState(); getGutter().repaint(); textArea.repaint(); } }
/** * Selects a range of text in a text component. If the new selection is outside of the previous * viewable rectangle, then the view is centered around the new selection. * * @param textArea The text component whose selection is to be centered. * @param start The start of the range to select. * @param end The end of the range to select. */ private static void selectAndPossiblyCenter(JTextArea textArea, int start, int end) { boolean foldsExpanded = false; if (textArea instanceof RSyntaxTextArea) { RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; FoldManager fm = rsta.getFoldManager(); if (fm.isCodeFoldingSupportedAndEnabled()) { foldsExpanded = fm.ensureOffsetNotInClosedFold(start); foldsExpanded |= fm.ensureOffsetNotInClosedFold(end); } } textArea.setSelectionStart(start); textArea.setSelectionEnd(end); Rectangle r = null; try { r = textArea.modelToView(start); if (r == null) { // Not yet visible; i.e. JUnit tests return; } if (end != start) { r = r.union(textArea.modelToView(end)); } } catch (BadLocationException ble) { // Never happens ble.printStackTrace(); textArea.setSelectionStart(start); textArea.setSelectionEnd(end); return; } Rectangle visible = textArea.getVisibleRect(); // If the new selection is already in the view, don't scroll, // as that is visually jarring. if (!foldsExpanded && visible.contains(r)) { textArea.setSelectionStart(start); textArea.setSelectionEnd(end); return; } visible.x = r.x - (visible.width - r.width) / 2; visible.y = r.y - (visible.height - r.height) / 2; Rectangle bounds = textArea.getBounds(); Insets i = textArea.getInsets(); bounds.x = i.left; bounds.y = i.top; bounds.width -= i.left + i.right; bounds.height -= i.top + i.bottom; if (visible.x < bounds.x) { visible.x = bounds.x; } if (visible.x + visible.width > bounds.x + bounds.width) { visible.x = bounds.x + bounds.width - visible.width; } if (visible.y < bounds.y) { visible.y = bounds.y; } if (visible.y + visible.height > bounds.y + bounds.height) { visible.y = bounds.y + bounds.height - visible.height; } textArea.scrollRectToVisible(visible); }
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; } }