Added
Link Here
|
1 |
package org.eclipse.jdt.internal.ui.javaeditor; |
2 |
|
3 |
import java.util.Iterator; |
4 |
|
5 |
import org.eclipse.swt.custom.StyledText; |
6 |
import org.eclipse.swt.graphics.Color; |
7 |
import org.eclipse.swt.graphics.GC; |
8 |
|
9 |
import org.eclipse.jface.text.BadLocationException; |
10 |
import org.eclipse.jface.text.IDocument; |
11 |
import org.eclipse.jface.text.IPainter; |
12 |
import org.eclipse.jface.text.IRegion; |
13 |
import org.eclipse.jface.text.Position; |
14 |
import org.eclipse.jface.text.source.Annotation; |
15 |
import org.eclipse.jface.text.source.AnnotationModel; |
16 |
import org.eclipse.jface.text.source.AnnotationPainter; |
17 |
import org.eclipse.jface.text.source.IAnnotationAccess; |
18 |
import org.eclipse.jface.text.source.IAnnotationModel; |
19 |
import org.eclipse.jface.text.source.IAnnotationModelExtension; |
20 |
import org.eclipse.jface.text.source.ISourceViewer; |
21 |
import org.eclipse.jface.text.source.ISourceViewerExtension2; |
22 |
|
23 |
import org.eclipse.ui.texteditor.IDocumentProvider; |
24 |
|
25 |
import org.eclipse.jdt.core.ElementChangedEvent; |
26 |
import org.eclipse.jdt.core.IElementChangedListener; |
27 |
import org.eclipse.jdt.core.IJavaElement; |
28 |
import org.eclipse.jdt.core.IJavaElementDelta; |
29 |
import org.eclipse.jdt.core.IParent; |
30 |
import org.eclipse.jdt.core.ISourceRange; |
31 |
import org.eclipse.jdt.core.ISourceReference; |
32 |
import org.eclipse.jdt.core.IType; |
33 |
import org.eclipse.jdt.core.ITypeRoot; |
34 |
import org.eclipse.jdt.core.JavaCore; |
35 |
import org.eclipse.jdt.core.JavaModelException; |
36 |
|
37 |
import org.eclipse.jdt.internal.ui.JavaPlugin; |
38 |
|
39 |
/** |
40 |
* Draws lines that visually demarcate the boundary for methods and types. |
41 |
* |
42 |
* @since 3.7 |
43 |
*/ |
44 |
class MethodBoundaryLinesProvider { |
45 |
|
46 |
/** |
47 |
* Updates the annotation model to reflect the incoming element changes. |
48 |
*/ |
49 |
private class ElementChangedListener implements IElementChangedListener { |
50 |
|
51 |
/* |
52 |
* @see org.eclipse.jdt.core.IElementChangedListener#elementChanged(org.eclipse.jdt.core.ElementChangedEvent) |
53 |
*/ |
54 |
public void elementChanged(ElementChangedEvent event) { |
55 |
IJavaElementDelta delta= findElement(fInput, event.getDelta()); |
56 |
if (delta != null && (delta.getFlags() & (IJavaElementDelta.F_CHILDREN | IJavaElementDelta.F_CONTENT)) != 0) { |
57 |
//System.out.println("Element Changed: " + delta); |
58 |
//if (shouldIgnoreDelta(event.getDelta().getCompilationUnitAST(), delta)) |
59 |
// return; |
60 |
if ((delta.getFlags() & IJavaElementDelta.F_CHILDREN) != 0) |
61 |
updateAnnotationModel(delta.getAffectedChildren()); |
62 |
else |
63 |
updateAnnotationPositions(); |
64 |
} |
65 |
} |
66 |
|
67 |
/** |
68 |
* Find the element in the java element delta that matches the target element. |
69 |
* |
70 |
* @param target the target java element to be searched for in the delta |
71 |
* @param delta the java element delta that is to be searched for the target element |
72 |
* @return the delta that contains the java element matching the target element |
73 |
*/ |
74 |
private IJavaElementDelta findElement(IJavaElement target, IJavaElementDelta delta) { |
75 |
|
76 |
if (delta == null || target == null) |
77 |
return null; |
78 |
|
79 |
IJavaElement element= delta.getElement(); |
80 |
|
81 |
if (element.getElementType() > IJavaElement.CLASS_FILE) |
82 |
return null; |
83 |
|
84 |
if (target.equals(element)) |
85 |
return delta; |
86 |
|
87 |
IJavaElementDelta[] children= delta.getAffectedChildren(); |
88 |
|
89 |
for (int i= 0; i < children.length; i++) { |
90 |
IJavaElementDelta d= findElement(target, children[i]); |
91 |
if (d != null) |
92 |
return d; |
93 |
} |
94 |
|
95 |
return null; |
96 |
} |
97 |
} |
98 |
|
99 |
/** |
100 |
* The annotation model that holds the annotations for method boundary lines. |
101 |
*/ |
102 |
private class MethodBoundaryAnnotationModel extends AnnotationModel { |
103 |
private MethodBoundaryAnnotationModel() { |
104 |
} |
105 |
|
106 |
/** |
107 |
* Sets the position for the annotation associated with a given element to the new position. |
108 |
* If position is null then the annotation, if found, is removed from the model. |
109 |
* |
110 |
* @param element the element whose corresponding annotation position is to be modified |
111 |
* @param newPosition The new position for the concerned annotation |
112 |
*/ |
113 |
public void modifyAnnotationForElement(IJavaElement element, Position newPosition) { |
114 |
MethodBoundaryAnnotation methodBoundaryAnnotation= (MethodBoundaryAnnotation)getAnnotationForElement(element); |
115 |
if (methodBoundaryAnnotation != null) |
116 |
modifyAnnotationPosition(methodBoundaryAnnotation, newPosition); |
117 |
} |
118 |
|
119 |
/** |
120 |
* Searches and returns the annotation associated with given element. |
121 |
* |
122 |
* @param element the element whose associated annotation we are looking for |
123 |
* @return returns the associated annotation if found, else returns null |
124 |
*/ |
125 |
public Object getAnnotationForElement(IJavaElement element) { |
126 |
Iterator iterator= getAnnotationIterator(); |
127 |
while (iterator.hasNext()) { |
128 |
MethodBoundaryAnnotation methodBoundaryAnnotation= (MethodBoundaryAnnotation)iterator.next(); |
129 |
if (element.equals(methodBoundaryAnnotation.getElement())) { |
130 |
return methodBoundaryAnnotation; |
131 |
} |
132 |
} |
133 |
return null; |
134 |
} |
135 |
} |
136 |
|
137 |
/** |
138 |
* The drawing strategy for method boundary lines draws the lines that visual separate methods |
139 |
* and types. |
140 |
*/ |
141 |
private static class MethodBoundaryDrawingStrategy implements AnnotationPainter.IDrawingStrategy { |
142 |
|
143 |
/* |
144 |
* @see org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy#draw(org.eclipse.swt.graphics.GC, org.eclipse.swt.custom.StyledText, int, int, org.eclipse.swt.graphics.Color) |
145 |
*/ |
146 |
public void draw(Annotation annotation, GC gc, StyledText textWidget, int offset, int length, Color color) { |
147 |
if (annotation instanceof MethodBoundaryAnnotation) { |
148 |
MethodBoundaryAnnotation methodBoundaryAnnotation= (MethodBoundaryAnnotation)annotation; |
149 |
if (gc != null) { |
150 |
int lineIndex= textWidget.getLineAtOffset(offset); |
151 |
int lineY= textWidget.getLinePixel(lineIndex); |
152 |
IJavaElement element= methodBoundaryAnnotation.getElement(); |
153 |
if (element.getElementType() == IJavaElement.TYPE) { |
154 |
//System.out.println(methodBoundaryAnnotation.getElement().getElementName() + ": Off-" + offset + " Len-" + length + " Width-" + 2); |
155 |
gc.setLineWidth(2); |
156 |
lineY++; |
157 |
} else { |
158 |
//System.out.println(methodBoundaryAnnotation.getElement().getElementName() + ": Off-" + offset + " Len-" + length + " Width-" + 0); |
159 |
gc.setLineWidth(0); |
160 |
} |
161 |
Color defaultColor= gc.getForeground(); |
162 |
gc.setForeground(color); |
163 |
gc.drawLine(2, lineY, textWidget.getClientArea().width, lineY); |
164 |
gc.setForeground(defaultColor); |
165 |
} else { |
166 |
//System.out.println("Clearing: " + methodBoundaryAnnotation.getElement().getElementName() + ": " + offset + " " + length); |
167 |
textWidget.redraw(2, textWidget.getLinePixel(textWidget.getLineAtOffset(offset)), textWidget.getClientArea().width, 2, true); |
168 |
} |
169 |
} |
170 |
} |
171 |
} |
172 |
|
173 |
/** |
174 |
* Annotation for method boundary lines. |
175 |
*/ |
176 |
private class MethodBoundaryAnnotation extends Annotation { |
177 |
|
178 |
/** |
179 |
* The type for method boundary annotation. |
180 |
*/ |
181 |
public static final String TYPE= "org.eclipse.separator"; //$NON-NLS-1$ |
182 |
|
183 |
/** |
184 |
* The java element associated with this annotation. |
185 |
*/ |
186 |
private IJavaElement fElementToBeAnnotated; |
187 |
|
188 |
/** |
189 |
* Creates a new method boundary annotation. |
190 |
* |
191 |
* @param element the java element that this annotation is associated with |
192 |
*/ |
193 |
public MethodBoundaryAnnotation(IJavaElement element) { |
194 |
super(TYPE, false, null); |
195 |
fElementToBeAnnotated= element; |
196 |
} |
197 |
|
198 |
/** |
199 |
* Getter for the java element associated with this annotation. |
200 |
* |
201 |
* @return returns the java element associated with this annotation |
202 |
*/ |
203 |
public IJavaElement getElement() { |
204 |
return fElementToBeAnnotated; |
205 |
} |
206 |
} |
207 |
|
208 |
/** |
209 |
* Paints the method boundary lines. |
210 |
*/ |
211 |
private class MethodBoundaryAnnotationsPainter extends AnnotationPainter { |
212 |
|
213 |
/** |
214 |
* Constructs a new <code>MethodSeparatorPainter</code>. |
215 |
* |
216 |
* @param sourceViewer the source viewer for the painter |
217 |
* @param access the annotation access |
218 |
*/ |
219 |
public MethodBoundaryAnnotationsPainter(ISourceViewer sourceViewer, IAnnotationAccess access) { |
220 |
super(sourceViewer, access); |
221 |
} |
222 |
|
223 |
/** |
224 |
* Retrieves the annotation model from the given source viewer. |
225 |
* |
226 |
* @param sourceViewer the source viewer |
227 |
* @return the source viewer's annotation model or <code>null</code> if none can be found |
228 |
*/ |
229 |
protected IAnnotationModel findAnnotationModel(ISourceViewer sourceViewer) { |
230 |
if (sourceViewer != null && sourceViewer instanceof ISourceViewerExtension2) |
231 |
return ((IAnnotationModelExtension)(((ISourceViewerExtension2)sourceViewer).getVisualAnnotationModel())).getAnnotationModel(METHOD_BOUNDARY); |
232 |
return null; |
233 |
} |
234 |
} |
235 |
|
236 |
/** |
237 |
* Key of the method boundary annotation model inside the visual annotation model. Also |
238 |
* internally used as key for the drawing strategy. |
239 |
*/ |
240 |
public final static Object METHOD_BOUNDARY= new Object(); |
241 |
/** |
242 |
* The source viewer associated with the editor. |
243 |
*/ |
244 |
private JavaSourceViewer fViewer; |
245 |
/** |
246 |
* The method boundary painter that paints the boundary lines. |
247 |
*/ |
248 |
private MethodBoundaryAnnotationsPainter fPainter; |
249 |
|
250 |
/** |
251 |
* The annotation access. |
252 |
*/ |
253 |
private IAnnotationAccess fAnnotationAccess; |
254 |
/** |
255 |
* The drawing strategy that is used for drawing the method boundary lines. |
256 |
*/ |
257 |
private static AnnotationPainter.IDrawingStrategy fDrawingStrategy; |
258 |
/** |
259 |
* The method boundary annotation model that holds the annotations and is connected to the |
260 |
* document. |
261 |
*/ |
262 |
private MethodBoundaryAnnotationModel fMethodBoundaryAnnotationModel; |
263 |
/** |
264 |
* The listener that listens for element changes from the java model. |
265 |
*/ |
266 |
private IElementChangedListener fElementListener; |
267 |
/** |
268 |
* The java input element associated with the java editor. |
269 |
*/ |
270 |
private IJavaElement fInput; |
271 |
/** |
272 |
* The java editor. |
273 |
*/ |
274 |
private JavaEditor fEditor; |
275 |
/** |
276 |
* Constructs the <code>MethodBoundaryLinesProvider</code>. |
277 |
* |
278 |
* @param editor the java editor |
279 |
* @param viewer the source viewer associated with the editor |
280 |
* @param annotationAccess the annotation access |
281 |
* @param methodBoundaryColor the color to be used for drawing the method boundary lines |
282 |
*/ |
283 |
public MethodBoundaryLinesProvider(JavaEditor editor, JavaSourceViewer viewer, IAnnotationAccess annotationAccess, Color methodBoundaryColor) { |
284 |
fEditor= editor; |
285 |
fViewer= viewer; |
286 |
fAnnotationAccess= annotationAccess; |
287 |
if (fPainter == null) { |
288 |
fPainter= new MethodBoundaryAnnotationsPainter(fViewer, fAnnotationAccess); |
289 |
fPainter.addDrawingStrategy(METHOD_BOUNDARY, getDrawingStrategy()); |
290 |
fPainter.addAnnotationType(MethodBoundaryAnnotation.TYPE, METHOD_BOUNDARY); |
291 |
fPainter.setAnnotationTypeColor(MethodBoundaryAnnotation.TYPE, methodBoundaryColor); |
292 |
fViewer.addPainter(fPainter); |
293 |
} |
294 |
|
295 |
fInput= EditorUtility.getEditorInputJavaElement(fEditor, false); |
296 |
fMethodBoundaryAnnotationModel= new MethodBoundaryAnnotationModel(); |
297 |
try { |
298 |
initializeModel(((IParent)fInput).getChildren()); |
299 |
} catch (JavaModelException e) { |
300 |
JavaPlugin.log(e); |
301 |
} |
302 |
((IAnnotationModelExtension)(fViewer.getVisualAnnotationModel())).addAnnotationModel(METHOD_BOUNDARY, fMethodBoundaryAnnotationModel); |
303 |
if (fElementListener == null) { |
304 |
//System.out.println("New Listener Registered: " + fEditor.getContentDescription()); |
305 |
fElementListener= new ElementChangedListener(); |
306 |
JavaCore.addElementChangedListener(fElementListener); |
307 |
} |
308 |
} |
309 |
|
310 |
/** |
311 |
* Initializes the annotation model with annotations based on the array of java elements. |
312 |
* |
313 |
* @param elements the java elements for which the annotation model is to be initialized |
314 |
*/ |
315 |
private void initializeModel(IJavaElement[] elements) { |
316 |
for (int i= 0; i < elements.length; i++) { |
317 |
int elementType= elements[i].getElementType(); |
318 |
try { |
319 |
if (isElementOfTypeWeCanAnnotate(elements[i])) { |
320 |
if (isMethodOrType(elementType)) { |
321 |
fMethodBoundaryAnnotationModel.addAnnotation(new MethodBoundaryAnnotation(elements[i]), getAlignedFirstLineElementPosition(elements[i])); |
322 |
} else if (i != 0 && isMethodOrType(elements[i - 1].getElementType())) { |
323 |
fMethodBoundaryAnnotationModel.addAnnotation(new MethodBoundaryAnnotation(elements[i]), getAlignedFirstLineElementPosition(elements[i])); |
324 |
} |
325 |
} |
326 |
if (elements[i] instanceof IParent) { |
327 |
IJavaElement[] children= ((IParent)elements[i]).getChildren(); |
328 |
if (children.length > 0) |
329 |
initializeModel(children); |
330 |
} |
331 |
} catch (JavaModelException e) { |
332 |
JavaPlugin.log(e); |
333 |
} |
334 |
} |
335 |
} |
336 |
|
337 |
/** |
338 |
* Get the aligned position of the first line of the java element. |
339 |
* |
340 |
* @param element the java element whose first line position is to be determined |
341 |
* @return returns the position of the first line of the java element |
342 |
*/ |
343 |
private Position getAlignedFirstLineElementPosition(IJavaElement element) { |
344 |
IDocument document= getDocument(); |
345 |
try { |
346 |
ISourceRange sourceRange= ((ISourceReference)element).getSourceRange(); |
347 |
IRegion elementFirstLineRegion= document.getLineInformationOfOffset(sourceRange.getOffset()); |
348 |
return new Position(elementFirstLineRegion.getOffset(), elementFirstLineRegion.getLength()); |
349 |
} catch (JavaModelException e) { |
350 |
JavaPlugin.log(e); |
351 |
} catch (BadLocationException e) { |
352 |
JavaPlugin.log(e); |
353 |
} |
354 |
return null; |
355 |
} |
356 |
|
357 |
/** |
358 |
* Returns <code>true</code> if the element type is one of the types that we can annotate and it |
359 |
* should not be of primary type. Types we can annotate are TYPE, METHOD, FIELD & INITIALIZER. |
360 |
* |
361 |
* @param element the element whose type is to be checked |
362 |
* @return <code>true</code> if element type matches any in our list |
363 |
*/ |
364 |
private boolean isElementOfTypeWeCanAnnotate(IJavaElement element) { |
365 |
int elementType= element.getElementType(); |
366 |
if (element instanceof ISourceReference && ((elementType == IJavaElement.TYPE && !isPrimaryType((IType)element)) |
367 |
|| elementType == IJavaElement.METHOD || elementType == IJavaElement.FIELD |
368 |
|| elementType == IJavaElement.INITIALIZER)) { |
369 |
return true; |
370 |
} |
371 |
return false; |
372 |
} |
373 |
|
374 |
/** |
375 |
* Returns <code>true</code> if <code>type</code> is not a top-level type, <code>false</code> if |
376 |
* it is. |
377 |
* |
378 |
* @param type the type to test |
379 |
* @return <code>true</code> if <code>type</code> is an inner type |
380 |
*/ |
381 |
private boolean isInnerType(IType type) { |
382 |
return type.getDeclaringType() != null; |
383 |
} |
384 |
|
385 |
/** |
386 |
* Returns <code>true</code> if <code>element</code> is the primary type, <code>false</code> if |
387 |
* it is not. This is based on {@link ITypeRoot#findPrimaryType()}. |
388 |
* |
389 |
* @param element the <code>element</code> to be evaluated if it is the primary type |
390 |
* @return <code>true</code> if it is the primary type |
391 |
*/ |
392 |
private boolean isPrimaryType(IType element) { |
393 |
IType primaryType= ((ITypeRoot)fInput).findPrimaryType(); |
394 |
if (primaryType != null && primaryType.equals(element)) |
395 |
return true; |
396 |
return false; |
397 |
} |
398 |
|
399 |
/** |
400 |
* Update the annotations in the method boundary annotation model with the |
401 |
* {@link IJavaElementDelta} changes. Based on ({@link IJavaElementDelta#getKind()}, annotation |
402 |
* corresponding to the element in the delta is added, removed or changed. |
403 |
* |
404 |
* @param delta the java element deltas that contain the changes done to the Java model |
405 |
*/ |
406 |
private void updateAnnotationModel(IJavaElementDelta[] delta) { |
407 |
for (int i= 0; i < delta.length; i++) { |
408 |
IJavaElement element= delta[i].getElement(); |
409 |
if (isElementOfTypeWeCanAnnotate(element)) { |
410 |
int elementType= element.getElementType(); |
411 |
int deltaKind= delta[i].getKind(); |
412 |
if (deltaKind == IJavaElementDelta.REMOVED) { |
413 |
//System.out.println("Element 'Removed': " + element.getElementName()); |
414 |
fMethodBoundaryAnnotationModel.modifyAnnotationForElement(element, null); |
415 |
updateAnnotationModelForDanglingElements(element.getParent()); |
416 |
|
417 |
} else if (deltaKind == IJavaElementDelta.ADDED) { |
418 |
if (!isMethodOrType(elementType) && isElementAfterTypeOrMethod(element)) { |
419 |
//modifyAnnotationForNextElement(element, false); |
420 |
addAnnotationForNewElementToModel(element); |
421 |
updateAnnotationModelForDanglingElements(element.getParent()); |
422 |
} else if (isMethodOrType(elementType)) { |
423 |
//modifyAnnotationForNextElement(element, true); |
424 |
addAnnotationForNewElementToModel(element); |
425 |
updateAnnotationModelForDanglingElements(element.getParent()); |
426 |
} |
427 |
} else if (deltaKind == IJavaElementDelta.CHANGED) { |
428 |
//System.out.println("Element 'Changed': " + element.getElementName()); |
429 |
fMethodBoundaryAnnotationModel.modifyAnnotationForElement(element, getAlignedFirstLineElementPosition(element)); |
430 |
} |
431 |
} |
432 |
if (element instanceof IParent) { |
433 |
updateAnnotationModel(delta[i].getAffectedChildren()); |
434 |
} |
435 |
} |
436 |
} |
437 |
|
438 |
/** |
439 |
* Return <code>true</code> if the given elementType is of type {@link IJavaElement#METHOD} or |
440 |
* {@link IJavaElement#TYPE}. |
441 |
* |
442 |
* @param elementType the element type to check against |
443 |
* @return <code>true</code> if the given elementType is of type {@link IJavaElement#METHOD} or |
444 |
* {@link IJavaElement#TYPE} |
445 |
*/ |
446 |
private boolean isMethodOrType(int elementType) { |
447 |
if (elementType == IJavaElement.METHOD || elementType == IJavaElement.TYPE) |
448 |
return true; |
449 |
return false; |
450 |
} |
451 |
|
452 |
/** |
453 |
* For all the children of parentElement, it checks and updates if any does not have a required |
454 |
* Method boundary. |
455 |
* |
456 |
* @param parentElement the parent element whose children are checked for missing boundary lines |
457 |
*/ |
458 |
private void updateAnnotationModelForDanglingElements(IJavaElement parentElement) { |
459 |
try { |
460 |
if (parentElement != null && parentElement.getElementType() == IJavaElement.TYPE && ((IType)parentElement).hasChildren()) { |
461 |
IJavaElement[] childrenElements= ((IType)parentElement).getChildren(); |
462 |
for (int i= 0; i < childrenElements.length; i++) { |
463 |
int childElementType= childrenElements[i].getElementType(); |
464 |
if (!isMethodOrType(childElementType)) { |
465 |
if (i == 0) { |
466 |
fMethodBoundaryAnnotationModel.modifyAnnotationForElement(childrenElements[i], null); |
467 |
} else { |
468 |
childElementType= childrenElements[i - 1].getElementType(); |
469 |
if (isMethodOrType(childElementType) && isElementOfTypeWeCanAnnotate(childrenElements[i]) |
470 |
&& fMethodBoundaryAnnotationModel.getAnnotationForElement(childrenElements[i]) == null) { |
471 |
fMethodBoundaryAnnotationModel.addAnnotation(new MethodBoundaryAnnotation(childrenElements[i]), getAlignedFirstLineElementPosition(childrenElements[i])); |
472 |
} else if (!isMethodOrType(childElementType)) { |
473 |
fMethodBoundaryAnnotationModel.modifyAnnotationForElement(childrenElements[i], null); |
474 |
} |
475 |
} |
476 |
} |
477 |
} |
478 |
} |
479 |
} catch (JavaModelException e) { |
480 |
JavaPlugin.log(e); |
481 |
} |
482 |
} |
483 |
|
484 |
/** |
485 |
* Returns <code>true</code> if the given element is immediately preceded by an element of type |
486 |
* IJavaElement.METHOD or TYPE in the source code. |
487 |
* |
488 |
* @param element the element |
489 |
* @return <code>true</code> if the given element is preceded by an IMethod or IType element |
490 |
*/ |
491 |
private boolean isElementAfterTypeOrMethod(IJavaElement element) { |
492 |
try { |
493 |
IJavaElement parentElement= element.getParent(); |
494 |
if (parentElement != null && parentElement.getElementType() == IJavaElement.TYPE && ((IType)parentElement).hasChildren()) { |
495 |
IJavaElement[] childrenElements= ((IType)parentElement).getChildren(); |
496 |
for (int i= 0; i < childrenElements.length; i++) { |
497 |
if (childrenElements[i].equals(element)) { |
498 |
if (i == 0) |
499 |
return false; |
500 |
int childElementType= childrenElements[i - 1].getElementType(); |
501 |
if (childElementType == IJavaElement.METHOD || (childElementType == IJavaElement.TYPE && isInnerType((IType)childrenElements[i - 1]))) { |
502 |
return true; |
503 |
} |
504 |
} |
505 |
} |
506 |
} |
507 |
} catch (JavaModelException e) { |
508 |
JavaPlugin.log(e); |
509 |
} |
510 |
return false; |
511 |
} |
512 |
|
513 |
/** |
514 |
* For a new element added to the Java, create and add an annotation to the method boundary |
515 |
* annotation model. |
516 |
* |
517 |
* @param element the new element for which annotation is to be added to the annotation model |
518 |
*/ |
519 |
private void addAnnotationForNewElementToModel(IJavaElement element) { |
520 |
//System.out.println("Element 'Added': " + element.getElementName()); |
521 |
fMethodBoundaryAnnotationModel.addAnnotation(new MethodBoundaryAnnotation(element), getAlignedFirstLineElementPosition(element)); |
522 |
if (element instanceof IParent) { |
523 |
try { |
524 |
IJavaElement[] children= ((IParent)element).getChildren(); |
525 |
for (int i= 0; i < children.length; i++) { |
526 |
int elementType= children[i].getElementType(); |
527 |
if (elementType == IJavaElement.METHOD || elementType == IJavaElement.TYPE) { |
528 |
addAnnotationForNewElementToModel(children[i]); |
529 |
} |
530 |
} |
531 |
} catch (JavaModelException e) { |
532 |
JavaPlugin.log(e); |
533 |
} |
534 |
} |
535 |
} |
536 |
|
537 |
/** |
538 |
* Update the Positions in the annotation model for all the elements whose current source range |
539 |
* in the document is different from the Position stored with the corresponding annotation. |
540 |
*/ |
541 |
private void updateAnnotationPositions() { |
542 |
Iterator iterator= fMethodBoundaryAnnotationModel.getAnnotationIterator(); |
543 |
while (iterator.hasNext()) { |
544 |
MethodBoundaryAnnotation methodBoundaryAnnotation= (MethodBoundaryAnnotation)iterator.next(); |
545 |
Position existingPosition= fMethodBoundaryAnnotationModel.getPosition(methodBoundaryAnnotation); |
546 |
IJavaElement element= methodBoundaryAnnotation.getElement(); |
547 |
if (element != null && ((ISourceReference)element).exists()) { |
548 |
Position newPosition= getAlignedFirstLineElementPosition(element); |
549 |
if (newPosition.getOffset() != existingPosition.getOffset() || newPosition.getLength() != existingPosition.getLength()) { |
550 |
fMethodBoundaryAnnotationModel.modifyAnnotationPosition(methodBoundaryAnnotation, newPosition); |
551 |
} |
552 |
} |
553 |
} |
554 |
} |
555 |
|
556 |
/** |
557 |
* Gets the document associated with the Java editor. |
558 |
* |
559 |
* @return returns the document |
560 |
*/ |
561 |
private IDocument getDocument() { |
562 |
JavaEditor editor= fEditor; |
563 |
if (editor == null) |
564 |
return null; |
565 |
|
566 |
IDocumentProvider provider= editor.getDocumentProvider(); |
567 |
if (provider == null) |
568 |
return null; |
569 |
|
570 |
return provider.getDocument(editor.getEditorInput()); |
571 |
} |
572 |
|
573 |
/** |
574 |
* Returns the drawing strategy to be used by the method boundary annotation painter. |
575 |
* |
576 |
* @return the drawing strategy to be used by the method boundary annotation painter |
577 |
*/ |
578 |
private AnnotationPainter.IDrawingStrategy getDrawingStrategy() { |
579 |
if (fDrawingStrategy == null) |
580 |
fDrawingStrategy= new MethodBoundaryDrawingStrategy(); |
581 |
return fDrawingStrategy; |
582 |
} |
583 |
|
584 |
/** |
585 |
* Disposes the method boundary lines provider and associated painter. |
586 |
*/ |
587 |
public void dispose() { |
588 |
if (fPainter != null) { |
589 |
fViewer.removePainter(fPainter); |
590 |
fPainter.deactivate(true); |
591 |
fPainter.dispose(); |
592 |
fPainter= null; |
593 |
} |
594 |
fMethodBoundaryAnnotationModel= null; |
595 |
JavaCore.removeElementChangedListener(fElementListener); |
596 |
fViewer= null; |
597 |
fEditor= null; |
598 |
} |
599 |
|
600 |
/** |
601 |
* Sets the color for the method boundary lines. |
602 |
* |
603 |
* @param methodBoundaryColor the color to be used for drawing the method boundary lines |
604 |
*/ |
605 |
public void setColor(Color methodBoundaryColor) { |
606 |
fPainter.setAnnotationTypeColor(MethodBoundaryAnnotation.TYPE, methodBoundaryColor); |
607 |
fPainter.paint(IPainter.CONFIGURATION); |
608 |
} |
609 |
} |