/* * 02/10/2009 * * LineHighlightManager - Manages line highlights. * Copyright (C) 2009 Robert Futrell * robert_futrell at users.sourceforge.net * http://fifesoft.com/rsyntaxtextarea * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ package org.fife.ui.rtextarea; import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.text.BadLocationException; import javax.swing.text.Position; /** * Manages line highlights in an <code>RTextArea</code>. * * @author Robert Futrell * @version 1.0 */ class LineHighlightManager { private RTextArea textArea; private List lineHighlights; /** * Constructor. * * @param textArea * The parent text area. */ public LineHighlightManager(RTextArea textArea) { this.textArea = textArea; } /** * Highlights the specified line. * * @param line * The line to highlight. * @param color * The color to highlight with. * @return A tag for the highlight. * @throws BadLocationException * If <code>line</code> is not a valid line number. * @see #removeLineHighlight(Object) */ public Object addLineHighlight(int line, Color color) throws BadLocationException { int offs = textArea.getLineStartOffset(line); LineHighlightInfo lhi = new LineHighlightInfo( textArea.getDocument().createPosition(offs), color); if (lineHighlights == null) { lineHighlights = new ArrayList(1); } int index = Collections.binarySearch(lineHighlights, lhi); if (index < 0) { // Common case index = -(index + 1); } lineHighlights.add(index, lhi); repaintLine(lhi); return lhi; } /** * Paints any highlighted lines in the specified line range. * * @param g * The graphics context. */ public void paintLineHighlights(Graphics g) { int count = lineHighlights == null ? 0 : lineHighlights.size(); if (count > 0) { int docLen = textArea.getDocument().getLength(); Rectangle vr = textArea.getVisibleRect(); int lineHeight = textArea.getLineHeight(); try { for (int i = 0; i < count; i++) { LineHighlightInfo lhi = (LineHighlightInfo) lineHighlights.get(i); int offs = lhi.getOffset(); if (offs >= 0 && offs <= docLen) { int y = textArea.yForLineContaining(offs); if (y > vr.y - lineHeight) { if (y < vr.y + vr.height) { g.setColor(lhi.getColor()); g.fillRect(0, y, textArea.getWidth(), lineHeight); } else { break; // Out of visible rect } } } } } catch (BadLocationException ble) { // Never happens ble.printStackTrace(); } } } /** * Removes all line highlights. * * @see #removeLineHighlight(Object) */ public void removeAllLineHighlights() { if (lineHighlights != null) { lineHighlights.clear(); textArea.repaint(); } } /** * Removes a line highlight. * * @param tag * The tag of the line highlight to remove. * @see #addLineHighlight(int, Color) */ public void removeLineHighlight(Object tag) { if (tag instanceof LineHighlightInfo) { lineHighlights.remove(tag); repaintLine((LineHighlightInfo) tag); } } /** * Repaints the line pointed to by the specified highlight information. * * @param lhi * The highlight information. */ private void repaintLine(LineHighlightInfo lhi) { int offs = lhi.getOffset(); // May be > length if they deleted text including the highlight if (offs >= 0 && offs <= textArea.getDocument().getLength()) { try { int y = textArea.yForLineContaining(offs); if (y > -1) { textArea.repaint(0, y, textArea.getWidth(), textArea.getLineHeight()); } } catch (BadLocationException ble) { ble.printStackTrace(); // Never happens } } } /** * Information about a line highlight. * * @author Robert Futrell * @version 1.0 */ private static class LineHighlightInfo implements Comparable { private Position offs; private Color color; public LineHighlightInfo(Position offs, Color c) { this.offs = offs; this.color = c; } public int compareTo(Object o) { if (o instanceof LineHighlightInfo) { return offs.getOffset() - ((LineHighlightInfo) o).getOffset(); } return -1; } public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof LineHighlightInfo) { return offs.getOffset() == ((LineHighlightInfo) o).getOffset(); } return false; } public Color getColor() { return color; } public int getOffset() { return offs.getOffset(); } public int hashCode() { return getOffset(); } } }