b0f7533b533a95e161f67dd8d5e46aea30a041f1
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / LinePainter.java
1 package net.sourceforge.phpeclipse.phpeditor;
2
3 /*
4  * (c) Copyright IBM Corp. 2000, 2001.
5  * All Rights Reserved.
6  */
7
8 import org.eclipse.jface.text.BadLocationException;
9 import org.eclipse.jface.text.IDocument;
10 import org.eclipse.jface.text.Position;
11 import org.eclipse.jface.text.source.ISourceViewer;
12 import org.eclipse.swt.custom.LineBackgroundEvent;
13 import org.eclipse.swt.custom.LineBackgroundListener;
14 import org.eclipse.swt.custom.StyledText;
15 import org.eclipse.swt.graphics.Color;
16 import org.eclipse.swt.graphics.Point;
17
18 public class LinePainter implements IPainter, LineBackgroundListener {
19
20         private final ISourceViewer fViewer;
21
22         private Color fHighlightColor;
23
24         private IPositionManager fPositionManager;
25
26         // positions to keep track of beginning and end of line to be painted or
27         // cleared
28         private Position fCurrentLine = new Position(0, 0);
29
30         private Position fLastLine = new Position(0, 0);
31
32         // used to keep track of the last line painted
33         private int fLastLineNumber = -1;
34
35         private boolean fIsActive;
36
37         public LinePainter(ISourceViewer sourceViewer) {
38                 fViewer = sourceViewer;
39         }
40
41         public void setHighlightColor(Color highlightColor) {
42                 fHighlightColor = highlightColor;
43         }
44
45         /*
46          * @see LineBackgroundListener#lineGetBackground(LineBackgroundEvent)
47          */
48         public void lineGetBackground(LineBackgroundEvent event) {
49                 // don't use cached line information because of asynch painting
50
51                 StyledText textWidget = fViewer.getTextWidget();
52                 if (textWidget != null) {
53
54                         int caret = textWidget.getCaretOffset();
55                         int length = event.lineText.length();
56
57                         if (event.lineOffset <= caret && caret <= event.lineOffset + length)
58                                 event.lineBackground = fHighlightColor;
59                         else
60                                 event.lineBackground = textWidget.getBackground();
61                 }
62         }
63
64         private boolean updateHighlightLine() {
65                 try {
66
67                         IDocument document = fViewer.getDocument();
68
69                         int offset = fViewer.getTextWidget().getCaretOffset()
70                                         + fViewer.getVisibleRegion().getOffset();
71                         int lineNumber = document.getLineOfOffset(offset);
72
73                         // redraw if the current line number is different from the last line
74                         // number we painted
75                         // initially fLastLineNumber is -1
76                         if (lineNumber != fLastLineNumber) {
77
78                                 fLastLine.offset = fCurrentLine.offset;
79                                 fLastLine.length = fCurrentLine.length;
80                                 fLastLine.isDeleted = fCurrentLine.isDeleted;
81
82                                 fCurrentLine.isDeleted = false;
83                                 fCurrentLine.offset = document.getLineOffset(lineNumber);
84                                 if (lineNumber == document.getNumberOfLines() - 1)
85                                         fCurrentLine.length = document.getLength()
86                                                         - fCurrentLine.offset;
87                                 else
88                                         fCurrentLine.length = document
89                                                         .getLineOffset(lineNumber + 1)
90                                                         - fCurrentLine.offset;
91
92                                 fLastLineNumber = lineNumber;
93                                 return true;
94
95                         }
96
97                 } catch (BadLocationException e) {
98                 }
99
100                 return false;
101         }
102
103         private void drawHighlightLine(Position position, int visibleOffset) {
104                 StyledText textWidget = fViewer.getTextWidget();
105
106                 // if the position that is about to be drawn was deleted then we can't
107                 if (position.isDeleted())
108                         return;
109
110                 int delta = position.offset - visibleOffset;
111                 if (0 <= delta && delta <= fViewer.getVisibleRegion().getLength()) {
112                         Point upperLeft = textWidget.getLocationAtOffset(delta);
113                         int width = textWidget.getClientArea().width
114                                         + textWidget.getHorizontalPixel();
115                         int height = textWidget.getLineHeight();
116                         textWidget.redraw(upperLeft.x, upperLeft.y, width, height, false);
117                 }
118         }
119
120         /*
121          * @see IPainter#deactivate(boolean)
122          */
123         public void deactivate(boolean redraw) {
124                 if (fIsActive) {
125                         fIsActive = false;
126
127                         /*
128                          * on turning off the feature one has to paint the currently
129                          * highlighted line with the standard background color
130                          */
131                         if (redraw)
132                                 drawHighlightLine(fCurrentLine, fViewer.getVisibleRegion()
133                                                 .getOffset());
134
135                         fViewer.getTextWidget().removeLineBackgroundListener(this);
136
137                         if (fPositionManager != null)
138                                 fPositionManager.removeManagedPosition(fCurrentLine);
139
140                         fLastLineNumber = -1;
141                 }
142         }
143
144         /*
145          * @see IPainter#dispose()
146          */
147         public void dispose() {
148         }
149
150         /*
151          * @see IPainter#paint(int)
152          */
153         public void paint(int reason) {
154
155                 // check selection
156                 Point selection = fViewer.getTextWidget().getSelectionRange();
157                 if (selection.y > 0) {
158                         deactivate(true);
159                         return;
160                 }
161
162                 // initialization
163                 if (!fIsActive) {
164                         fViewer.getTextWidget().addLineBackgroundListener(this);
165                         fPositionManager.addManagedPosition(fCurrentLine);
166                         fIsActive = true;
167                 }
168
169                 // redraw line highlight only if it hasn't been drawn yet on the
170                 // respective line
171                 if (updateHighlightLine()) {
172                         // used to handle segmented view of source files
173                         int visibleRegionOffset = fViewer.getVisibleRegion().getOffset();
174                         // clear last line
175                         drawHighlightLine(fLastLine, visibleRegionOffset);
176                         // draw new line
177                         drawHighlightLine(fCurrentLine, visibleRegionOffset);
178                 }
179         }
180
181         /*
182          * @see IPainter#setPositionManager(IPositionManager)
183          */
184         public void setPositionManager(IPositionManager manager) {
185                 fPositionManager = manager;
186         }
187 }