comparison org.eclipse.jface.text/src/org/eclipse/jface/text/source/MatchingCharacterPainter.d @ 12:bc29606a740c

Added dwt-addons in original directory structure of eclipse.org
author Frank Benoit <benoit@tionex.de>
date Sat, 14 Mar 2009 18:23:29 +0100
parents
children
comparison
equal deleted inserted replaced
11:43904fec5dca 12:bc29606a740c
1 /*******************************************************************************
2 * Copyright (c) 2000, 2005 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module org.eclipse.jface.text.source.MatchingCharacterPainter;
14
15 import org.eclipse.jface.text.source.ISharedTextColors; // packageimport
16 import org.eclipse.jface.text.source.ILineRange; // packageimport
17 import org.eclipse.jface.text.source.IAnnotationPresentation; // packageimport
18 import org.eclipse.jface.text.source.IVerticalRulerInfoExtension; // packageimport
19 import org.eclipse.jface.text.source.ICharacterPairMatcher; // packageimport
20 import org.eclipse.jface.text.source.TextInvocationContext; // packageimport
21 import org.eclipse.jface.text.source.LineChangeHover; // packageimport
22 import org.eclipse.jface.text.source.IChangeRulerColumn; // packageimport
23 import org.eclipse.jface.text.source.IAnnotationMap; // packageimport
24 import org.eclipse.jface.text.source.IAnnotationModelListenerExtension; // packageimport
25 import org.eclipse.jface.text.source.ISourceViewerExtension2; // packageimport
26 import org.eclipse.jface.text.source.IAnnotationHover; // packageimport
27 import org.eclipse.jface.text.source.ContentAssistantFacade; // packageimport
28 import org.eclipse.jface.text.source.IAnnotationAccess; // packageimport
29 import org.eclipse.jface.text.source.IVerticalRulerExtension; // packageimport
30 import org.eclipse.jface.text.source.IVerticalRulerColumn; // packageimport
31 import org.eclipse.jface.text.source.LineNumberRulerColumn; // packageimport
32 import org.eclipse.jface.text.source.IAnnotationModelExtension; // packageimport
33 import org.eclipse.jface.text.source.ILineDifferExtension; // packageimport
34 import org.eclipse.jface.text.source.DefaultCharacterPairMatcher; // packageimport
35 import org.eclipse.jface.text.source.LineNumberChangeRulerColumn; // packageimport
36 import org.eclipse.jface.text.source.IAnnotationAccessExtension; // packageimport
37 import org.eclipse.jface.text.source.ISourceViewer; // packageimport
38 import org.eclipse.jface.text.source.AnnotationModel; // packageimport
39 import org.eclipse.jface.text.source.ILineDifferExtension2; // packageimport
40 import org.eclipse.jface.text.source.IAnnotationModelListener; // packageimport
41 import org.eclipse.jface.text.source.IVerticalRuler; // packageimport
42 import org.eclipse.jface.text.source.DefaultAnnotationHover; // packageimport
43 import org.eclipse.jface.text.source.SourceViewer; // packageimport
44 import org.eclipse.jface.text.source.SourceViewerConfiguration; // packageimport
45 import org.eclipse.jface.text.source.AnnotationBarHoverManager; // packageimport
46 import org.eclipse.jface.text.source.CompositeRuler; // packageimport
47 import org.eclipse.jface.text.source.ImageUtilities; // packageimport
48 import org.eclipse.jface.text.source.VisualAnnotationModel; // packageimport
49 import org.eclipse.jface.text.source.IAnnotationModel; // packageimport
50 import org.eclipse.jface.text.source.ISourceViewerExtension3; // packageimport
51 import org.eclipse.jface.text.source.ILineDiffInfo; // packageimport
52 import org.eclipse.jface.text.source.VerticalRulerEvent; // packageimport
53 import org.eclipse.jface.text.source.ChangeRulerColumn; // packageimport
54 import org.eclipse.jface.text.source.ILineDiffer; // packageimport
55 import org.eclipse.jface.text.source.AnnotationModelEvent; // packageimport
56 import org.eclipse.jface.text.source.AnnotationColumn; // packageimport
57 import org.eclipse.jface.text.source.AnnotationRulerColumn; // packageimport
58 import org.eclipse.jface.text.source.IAnnotationHoverExtension; // packageimport
59 import org.eclipse.jface.text.source.AbstractRulerColumn; // packageimport
60 import org.eclipse.jface.text.source.ISourceViewerExtension; // packageimport
61 import org.eclipse.jface.text.source.AnnotationMap; // packageimport
62 import org.eclipse.jface.text.source.IVerticalRulerInfo; // packageimport
63 import org.eclipse.jface.text.source.IAnnotationModelExtension2; // packageimport
64 import org.eclipse.jface.text.source.LineRange; // packageimport
65 import org.eclipse.jface.text.source.IAnnotationAccessExtension2; // packageimport
66 import org.eclipse.jface.text.source.VerticalRuler; // packageimport
67 import org.eclipse.jface.text.source.JFaceTextMessages; // packageimport
68 import org.eclipse.jface.text.source.IOverviewRuler; // packageimport
69 import org.eclipse.jface.text.source.Annotation; // packageimport
70 import org.eclipse.jface.text.source.IVerticalRulerListener; // packageimport
71 import org.eclipse.jface.text.source.ISourceViewerExtension4; // packageimport
72 import org.eclipse.jface.text.source.AnnotationPainter; // packageimport
73 import org.eclipse.jface.text.source.IAnnotationHoverExtension2; // packageimport
74 import org.eclipse.jface.text.source.OverviewRuler; // packageimport
75 import org.eclipse.jface.text.source.OverviewRulerHoverManager; // packageimport
76
77
78 import java.lang.all;
79 import java.util.Set;
80
81
82
83
84 import org.eclipse.swt.custom.StyledText;
85 import org.eclipse.swt.events.PaintEvent;
86 import org.eclipse.swt.events.PaintListener;
87 import org.eclipse.swt.graphics.Color;
88 import org.eclipse.swt.graphics.GC;
89 import org.eclipse.swt.graphics.Point;
90 import org.eclipse.swt.graphics.Rectangle;
91 import org.eclipse.jface.text.BadLocationException;
92 import org.eclipse.jface.text.IDocument;
93 import org.eclipse.jface.text.IPaintPositionManager;
94 import org.eclipse.jface.text.IPainter;
95 import org.eclipse.jface.text.IRegion;
96 import org.eclipse.jface.text.ITextViewerExtension5;
97 import org.eclipse.jface.text.Position;
98 import org.eclipse.jface.text.Region;
99
100 /**
101 * Highlights the peer character matching the character near the caret position.
102 * This painter can be configured with an
103 * {@link org.eclipse.jface.text.source.ICharacterPairMatcher}.
104 * <p>
105 * Clients instantiate and configure object of this class.</p>
106 *
107 * @since 2.1
108 */
109 public final class MatchingCharacterPainter : IPainter, PaintListener {
110
111 /** Indicates whether this painter is active */
112 private bool fIsActive= false;
113 /** The source viewer this painter is associated with */
114 private ISourceViewer fSourceViewer;
115 /** The viewer's widget */
116 private StyledText fTextWidget;
117 /** The color in which to highlight the peer character */
118 private Color fColor;
119 /** The paint position manager */
120 private IPaintPositionManager fPaintPositionManager;
121 /** The strategy for finding matching characters */
122 private ICharacterPairMatcher fMatcher;
123 /** The position tracking the matching characters */
124 private Position fPairPosition;
125 /** The anchor indicating whether the character is left or right of the caret */
126 private int fAnchor;
127
128
129 /**
130 * Creates a new MatchingCharacterPainter for the given source viewer using
131 * the given character pair matcher. The character matcher is not adopted by
132 * this painter. Thus, it is not disposed. However, this painter requires
133 * exclusive access to the given pair matcher.
134 *
135 * @param sourceViewer
136 * @param matcher
137 */
138 public this(ISourceViewer sourceViewer, ICharacterPairMatcher matcher) {
139 fPairPosition= new Position(0, 0);
140 fSourceViewer= sourceViewer;
141 fMatcher= matcher;
142 fTextWidget= sourceViewer.getTextWidget();
143 }
144
145 /**
146 * Sets the color in which to highlight the match character.
147 *
148 * @param color the color
149 */
150 public void setColor(Color color) {
151 fColor= color;
152 }
153
154 /*
155 * @see org.eclipse.jface.text.IPainter#dispose()
156 */
157 public void dispose() {
158 if (fMatcher !is null) {
159 fMatcher.clear();
160 fMatcher= null;
161 }
162
163 fColor= null;
164 fTextWidget= null;
165 }
166
167 /*
168 * @see org.eclipse.jface.text.IPainter#deactivate(bool)
169 */
170 public void deactivate(bool redraw) {
171 if (fIsActive) {
172 fIsActive= false;
173 fTextWidget.removePaintListener(this);
174 if (fPaintPositionManager !is null)
175 fPaintPositionManager.unmanagePosition(fPairPosition);
176 if (redraw)
177 handleDrawRequest(null);
178 }
179 }
180
181 /*
182 * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
183 */
184 public void paintControl(PaintEvent event) {
185 if (fTextWidget !is null)
186 handleDrawRequest(event.gc);
187 }
188
189 /**
190 * Handles a redraw request.
191 *
192 * @param gc the GC to draw into.
193 */
194 private void handleDrawRequest(GC gc) {
195
196 if (fPairPosition.isDeleted)
197 return;
198
199 int offset= fPairPosition.getOffset();
200 int length= fPairPosition.getLength();
201 if (length < 1)
202 return;
203
204 if ( cast(ITextViewerExtension5)fSourceViewer ) {
205 ITextViewerExtension5 extension= cast(ITextViewerExtension5) fSourceViewer;
206 IRegion widgetRange= extension.modelRange2WidgetRange(new Region(offset, length));
207 if (widgetRange is null)
208 return;
209
210 try {
211 // don't draw if the pair position is really hidden and widgetRange just
212 // marks the coverage around it.
213 IDocument doc= fSourceViewer.getDocument();
214 int startLine= doc.getLineOfOffset(offset);
215 int endLine= doc.getLineOfOffset(offset + length);
216 if (extension.modelLine2WidgetLine(startLine) is -1 || extension.modelLine2WidgetLine(endLine) is -1)
217 return;
218 } catch (BadLocationException e) {
219 return;
220 }
221
222 offset= widgetRange.getOffset();
223 length= widgetRange.getLength();
224
225 } else {
226 IRegion region= fSourceViewer.getVisibleRegion();
227 if (region.getOffset() > offset || region.getOffset() + region.getLength() < offset + length)
228 return;
229 offset -= region.getOffset();
230 }
231
232 if (ICharacterPairMatcher.RIGHT is fAnchor)
233 draw(gc, offset, 1);
234 else
235 draw(gc, offset + length -1, 1);
236 }
237
238 /**
239 * Highlights the given widget region.
240 *
241 * @param gc the GC to draw into
242 * @param offset the offset of the widget region
243 * @param length the length of the widget region
244 */
245 private void draw(GC gc, int offset, int length) {
246 if (gc !is null) {
247
248 gc.setForeground(fColor);
249
250 Rectangle bounds;
251 if (length > 0)
252 bounds= fTextWidget.getTextBounds(offset, offset + length - 1);
253 else {
254 Point loc= fTextWidget.getLocationAtOffset(offset);
255 bounds= new Rectangle(loc.x, loc.y, 1, fTextWidget.getLineHeight(offset));
256 }
257
258 // draw box around line segment
259 gc.drawRectangle(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1);
260
261 // draw box around character area
262 // int widgetBaseline= fTextWidget.getBaseline();
263 // FontMetrics fm= gc.getFontMetrics();
264 // int fontBaseline= fm.getAscent() + fm.getLeading();
265 // int fontBias= widgetBaseline - fontBaseline;
266
267 // gc.drawRectangle(left.x, left.y + fontBias, right.x - left.x - 1, fm.getHeight() - 1);
268
269 } else {
270 fTextWidget.redrawRange(offset, length, true);
271 }
272 }
273
274 /*
275 * @see org.eclipse.jface.text.IPainter#paint(int)
276 */
277 public void paint(int reason) {
278
279 IDocument document= fSourceViewer.getDocument();
280 if (document is null) {
281 deactivate(false);
282 return;
283 }
284
285 Point selection= fSourceViewer.getSelectedRange();
286 if (selection.y > 0) {
287 deactivate(true);
288 return;
289 }
290
291 IRegion pair= fMatcher.match(document, selection.x);
292 if (pair is null) {
293 deactivate(true);
294 return;
295 }
296
297 if (fIsActive) {
298
299 if (IPainter.CONFIGURATION is reason) {
300
301 // redraw current highlighting
302 handleDrawRequest(null);
303
304 } else if (pair.getOffset() !is fPairPosition.getOffset() ||
305 pair.getLength() !is fPairPosition.getLength() ||
306 fMatcher.getAnchor() !is fAnchor) {
307
308 // otherwise only do something if position is different
309
310 // remove old highlighting
311 handleDrawRequest(null);
312 // update position
313 fPairPosition.isDeleted_= false;
314 fPairPosition.offset= pair.getOffset();
315 fPairPosition.length= pair.getLength();
316 fAnchor= fMatcher.getAnchor();
317 // apply new highlighting
318 handleDrawRequest(null);
319
320 }
321 } else {
322
323 fIsActive= true;
324
325 fPairPosition.isDeleted_= false;
326 fPairPosition.offset= pair.getOffset();
327 fPairPosition.length= pair.getLength();
328 fAnchor= fMatcher.getAnchor();
329
330 fTextWidget.addPaintListener(this);
331 fPaintPositionManager.managePosition(fPairPosition);
332 handleDrawRequest(null);
333 }
334 }
335
336 /*
337 * @see org.eclipse.jface.text.IPainter#setPositionManager(org.eclipse.jface.text.IPaintPositionManager)
338 */
339 public void setPositionManager(IPaintPositionManager manager) {
340 fPaintPositionManager= manager;
341 }
342 }