--- /dev/null
+package net.sourceforge.phpeclipse.phpeditor;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.swt.custom.LineBackgroundEvent;
+import org.eclipse.swt.custom.LineBackgroundListener;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Point;
+
+public class LinePainter implements IPainter, LineBackgroundListener {
+
+ private final ISourceViewer fViewer;
+
+ private Color fHighlightColor;
+
+ private IPositionManager fPositionManager;
+
+ // positions to keep track of beginning and end of line to be painted or
+ // cleared
+ private Position fCurrentLine = new Position(0, 0);
+
+ private Position fLastLine = new Position(0, 0);
+
+ // used to keep track of the last line painted
+ private int fLastLineNumber = -1;
+
+ private boolean fIsActive;
+
+ public LinePainter(ISourceViewer sourceViewer) {
+ fViewer = sourceViewer;
+ }
+
+ public void setHighlightColor(Color highlightColor) {
+ fHighlightColor = highlightColor;
+ }
+
+ /*
+ * @see LineBackgroundListener#lineGetBackground(LineBackgroundEvent)
+ */
+ public void lineGetBackground(LineBackgroundEvent event) {
+ // don't use cached line information because of asynch painting
+
+ StyledText textWidget = fViewer.getTextWidget();
+ if (textWidget != null) {
+
+ int caret = textWidget.getCaretOffset();
+ int length = event.lineText.length();
+
+ if (event.lineOffset <= caret && caret <= event.lineOffset + length)
+ event.lineBackground = fHighlightColor;
+ else
+ event.lineBackground = textWidget.getBackground();
+ }
+ }
+
+ private boolean updateHighlightLine() {
+ try {
+
+ IDocument document = fViewer.getDocument();
+
+ int offset = fViewer.getTextWidget().getCaretOffset()
+ + fViewer.getVisibleRegion().getOffset();
+ int lineNumber = document.getLineOfOffset(offset);
+
+ // redraw if the current line number is different from the last line
+ // number we painted
+ // initially fLastLineNumber is -1
+ if (lineNumber != fLastLineNumber) {
+
+ fLastLine.offset = fCurrentLine.offset;
+ fLastLine.length = fCurrentLine.length;
+ fLastLine.isDeleted = fCurrentLine.isDeleted;
+
+ fCurrentLine.isDeleted = false;
+ fCurrentLine.offset = document.getLineOffset(lineNumber);
+ if (lineNumber == document.getNumberOfLines() - 1)
+ fCurrentLine.length = document.getLength()
+ - fCurrentLine.offset;
+ else
+ fCurrentLine.length = document
+ .getLineOffset(lineNumber + 1)
+ - fCurrentLine.offset;
+
+ fLastLineNumber = lineNumber;
+ return true;
+
+ }
+
+ } catch (BadLocationException e) {
+ }
+
+ return false;
+ }
+
+ private void drawHighlightLine(Position position, int visibleOffset) {
+ StyledText textWidget = fViewer.getTextWidget();
+
+ // if the position that is about to be drawn was deleted then we can't
+ if (position.isDeleted())
+ return;
+
+ int delta = position.offset - visibleOffset;
+ if (0 <= delta && delta <= fViewer.getVisibleRegion().getLength()) {
+ Point upperLeft = textWidget.getLocationAtOffset(delta);
+ int width = textWidget.getClientArea().width
+ + textWidget.getHorizontalPixel();
+ int height = textWidget.getLineHeight();
+ textWidget.redraw(upperLeft.x, upperLeft.y, width, height, false);
+ }
+ }
+
+ /*
+ * @see IPainter#deactivate(boolean)
+ */
+ public void deactivate(boolean redraw) {
+ if (fIsActive) {
+ fIsActive = false;
+
+ /*
+ * on turning off the feature one has to paint the currently
+ * highlighted line with the standard background color
+ */
+ if (redraw)
+ drawHighlightLine(fCurrentLine, fViewer.getVisibleRegion()
+ .getOffset());
+
+ fViewer.getTextWidget().removeLineBackgroundListener(this);
+
+ if (fPositionManager != null)
+ fPositionManager.removeManagedPosition(fCurrentLine);
+
+ fLastLineNumber = -1;
+ }
+ }
+
+ /*
+ * @see IPainter#dispose()
+ */
+ public void dispose() {
+ }
+
+ /*
+ * @see IPainter#paint(int)
+ */
+ public void paint(int reason) {
+
+ // check selection
+ Point selection = fViewer.getTextWidget().getSelectionRange();
+ if (selection.y > 0) {
+ deactivate(true);
+ return;
+ }
+
+ // initialization
+ if (!fIsActive) {
+ fViewer.getTextWidget().addLineBackgroundListener(this);
+ fPositionManager.addManagedPosition(fCurrentLine);
+ fIsActive = true;
+ }
+
+ // redraw line highlight only if it hasn't been drawn yet on the
+ // respective line
+ if (updateHighlightLine()) {
+ // used to handle segmented view of source files
+ int visibleRegionOffset = fViewer.getVisibleRegion().getOffset();
+ // clear last line
+ drawHighlightLine(fLastLine, visibleRegionOffset);
+ // draw new line
+ drawHighlightLine(fCurrentLine, visibleRegionOffset);
+ }
+ }
+
+ /*
+ * @see IPainter#setPositionManager(IPositionManager)
+ */
+ public void setPositionManager(IPositionManager manager) {
+ fPositionManager = manager;
+ }
+}
\ No newline at end of file