KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > text > correction > QuickAssistLightBulbUpdater


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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  *******************************************************************************/

11 package org.eclipse.jdt.internal.ui.text.correction;
12
13 import java.util.ConcurrentModificationException JavaDoc;
14 import java.util.Iterator JavaDoc;
15
16 import org.eclipse.swt.SWT;
17 import org.eclipse.swt.graphics.GC;
18 import org.eclipse.swt.graphics.Image;
19 import org.eclipse.swt.graphics.Point;
20 import org.eclipse.swt.graphics.Rectangle;
21 import org.eclipse.swt.widgets.Canvas;
22
23 import org.eclipse.jface.util.IPropertyChangeListener;
24 import org.eclipse.jface.util.PropertyChangeEvent;
25
26 import org.eclipse.jface.text.BadLocationException;
27 import org.eclipse.jface.text.IDocument;
28 import org.eclipse.jface.text.ITextSelection;
29 import org.eclipse.jface.text.ITextViewer;
30 import org.eclipse.jface.text.Position;
31 import org.eclipse.jface.text.source.Annotation;
32 import org.eclipse.jface.text.source.IAnnotationAccessExtension;
33 import org.eclipse.jface.text.source.IAnnotationModel;
34 import org.eclipse.jface.text.source.IAnnotationPresentation;
35 import org.eclipse.jface.text.source.ImageUtilities;
36
37 import org.eclipse.ui.IEditorPart;
38 import org.eclipse.ui.texteditor.AnnotationPreference;
39 import org.eclipse.ui.texteditor.ITextEditor;
40
41 import org.eclipse.ui.editors.text.EditorsUI;
42
43 import org.eclipse.jdt.core.ICompilationUnit;
44 import org.eclipse.jdt.core.IJavaElement;
45 import org.eclipse.jdt.core.dom.CompilationUnit;
46
47 import org.eclipse.jdt.ui.JavaUI;
48 import org.eclipse.jdt.ui.PreferenceConstants;
49 import org.eclipse.jdt.ui.text.java.IInvocationContext;
50
51 import org.eclipse.jdt.internal.ui.JavaPluginImages;
52 import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
53 import org.eclipse.jdt.internal.ui.viewsupport.ISelectionListenerWithAST;
54 import org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager;
55
56 /**
57  *
58  */

59 public class QuickAssistLightBulbUpdater {
60
61     public static class AssistAnnotation extends Annotation implements IAnnotationPresentation {
62
63         //XXX: To be fully correct this should be a non-static fields in QuickAssistLightBulbUpdater
64
private static final int LAYER;
65
66         static {
67             Annotation annotation= new Annotation("org.eclipse.jdt.ui.warning", false, null); //$NON-NLS-1$
68
AnnotationPreference preference= EditorsUI.getAnnotationPreferenceLookup().getAnnotationPreference(annotation);
69             if (preference != null)
70                 LAYER= preference.getPresentationLayer() - 1;
71             else
72                 LAYER= IAnnotationAccessExtension.DEFAULT_LAYER;
73
74         }
75
76         private Image fImage;
77
78         public AssistAnnotation() {
79         }
80
81         /*
82          * @see org.eclipse.jface.text.source.IAnnotationPresentation#getLayer()
83          */

84         public int getLayer() {
85             return LAYER;
86         }
87
88         private Image getImage() {
89             if (fImage == null) {
90                 fImage= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_QUICK_ASSIST);
91             }
92             return fImage;
93         }
94
95         /* (non-Javadoc)
96          * @see org.eclipse.jface.text.source.Annotation#paint(org.eclipse.swt.graphics.GC, org.eclipse.swt.widgets.Canvas, org.eclipse.swt.graphics.Rectangle)
97          */

98         public void paint(GC gc, Canvas canvas, Rectangle r) {
99             ImageUtilities.drawImage(getImage(), gc, canvas, r, SWT.CENTER, SWT.TOP);
100         }
101
102     }
103
104     private final Annotation fAnnotation;
105     private boolean fIsAnnotationShown;
106     private ITextEditor fEditor;
107     private ITextViewer fViewer;
108
109     private ISelectionListenerWithAST fListener;
110     private IPropertyChangeListener fPropertyChangeListener;
111
112     public QuickAssistLightBulbUpdater(ITextEditor part, ITextViewer viewer) {
113         fEditor= part;
114         fViewer= viewer;
115         fAnnotation= new AssistAnnotation();
116         fIsAnnotationShown= false;
117         fPropertyChangeListener= null;
118     }
119
120     public boolean isSetInPreferences() {
121         return PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_QUICKASSIST_LIGHTBULB);
122     }
123
124     private void installSelectionListener() {
125         fListener= new ISelectionListenerWithAST() {
126             public void selectionChanged(IEditorPart part, ITextSelection selection, CompilationUnit astRoot) {
127                 doSelectionChanged(selection.getOffset(), selection.getLength(), astRoot);
128             }
129         };
130         SelectionListenerWithASTManager.getDefault().addListener(fEditor, fListener);
131     }
132
133     private void uninstallSelectionListener() {
134         if (fListener != null) {
135             SelectionListenerWithASTManager.getDefault().removeListener(fEditor, fListener);
136             fListener= null;
137         }
138         IAnnotationModel model= getAnnotationModel();
139         if (model != null) {
140             removeLightBulb(model);
141         }
142     }
143
144     public void install() {
145         if (isSetInPreferences()) {
146             installSelectionListener();
147         }
148         if (fPropertyChangeListener == null) {
149             fPropertyChangeListener= new IPropertyChangeListener() {
150                 public void propertyChange(PropertyChangeEvent event) {
151                     doPropertyChanged(event.getProperty());
152                 }
153             };
154             PreferenceConstants.getPreferenceStore().addPropertyChangeListener(fPropertyChangeListener);
155         }
156     }
157
158     public void uninstall() {
159         uninstallSelectionListener();
160         if (fPropertyChangeListener != null) {
161             PreferenceConstants.getPreferenceStore().removePropertyChangeListener(fPropertyChangeListener);
162             fPropertyChangeListener= null;
163         }
164     }
165
166     protected void doPropertyChanged(String JavaDoc property) {
167         if (property.equals(PreferenceConstants.EDITOR_QUICKASSIST_LIGHTBULB)) {
168             if (isSetInPreferences()) {
169                 ICompilationUnit cu= getCompilationUnit();
170                 if (cu != null) {
171                     installSelectionListener();
172                     Point point= fViewer.getSelectedRange();
173                     CompilationUnit astRoot= ASTProvider.getASTProvider().getAST(cu, ASTProvider.WAIT_ACTIVE_ONLY, null);
174                     if (astRoot != null) {
175                         doSelectionChanged(point.x, point.y, astRoot);
176                     }
177                 }
178             } else {
179                 uninstallSelectionListener();
180             }
181         }
182     }
183
184     private ICompilationUnit getCompilationUnit() {
185         IJavaElement elem= JavaUI.getEditorInputJavaElement(fEditor.getEditorInput());
186         if (elem instanceof ICompilationUnit) {
187             return (ICompilationUnit) elem;
188         }
189         return null;
190     }
191
192     private IAnnotationModel getAnnotationModel() {
193         return JavaUI.getDocumentProvider().getAnnotationModel(fEditor.getEditorInput());
194     }
195
196     private IDocument getDocument() {
197         return JavaUI.getDocumentProvider().getDocument(fEditor.getEditorInput());
198     }
199
200
201     private void doSelectionChanged(int offset, int length, CompilationUnit astRoot) {
202
203         final IAnnotationModel model= getAnnotationModel();
204         final ICompilationUnit cu= getCompilationUnit();
205         if (model == null || cu == null) {
206             return;
207         }
208
209         final AssistContext context= new AssistContext(cu, offset, length);
210         context.setASTRoot(astRoot);
211
212         boolean hasQuickFix= hasQuickFixLightBulb(model, context.getSelectionOffset());
213         if (hasQuickFix) {
214             removeLightBulb(model);
215             return; // there is already a quick fix light bulb at the new location
216
}
217
218         calculateLightBulb(model, context);
219     }
220
221     /*
222      * Needs to be called synchronized
223      */

224     private void calculateLightBulb(IAnnotationModel model, IInvocationContext context) {
225         boolean needsAnnotation= JavaCorrectionProcessor.hasAssists(context);
226         if (fIsAnnotationShown) {
227             model.removeAnnotation(fAnnotation);
228         }
229         if (needsAnnotation) {
230             model.addAnnotation(fAnnotation, new Position(context.getSelectionOffset(), context.getSelectionLength()));
231         }
232         fIsAnnotationShown= needsAnnotation;
233     }
234
235     private void removeLightBulb(IAnnotationModel model) {
236         synchronized (this) {
237             if (fIsAnnotationShown) {
238                 model.removeAnnotation(fAnnotation);
239                 fIsAnnotationShown= false;
240             }
241         }
242     }
243
244     /*
245      * Tests if there is already a quick fix light bulb on the current line
246      */

247     private boolean hasQuickFixLightBulb(IAnnotationModel model, int offset) {
248         try {
249             IDocument document= getDocument();
250             if (document == null) {
251                 return false;
252             }
253
254             // we access a document and annotation model from within a job
255
// since these are only read accesses, we won't hurt anyone else if
256
// this goes boink
257

258             // may throw an IndexOutOfBoundsException upon concurrent document modification
259
int currLine= document.getLineOfOffset(offset);
260
261             // this iterator is not protected, it may throw ConcurrentModificationExceptions
262
Iterator JavaDoc iter= model.getAnnotationIterator();
263             while (iter.hasNext()) {
264                 Annotation annot= (Annotation) iter.next();
265                 if (JavaCorrectionProcessor.isQuickFixableType(annot)) {
266                     // may throw an IndexOutOfBoundsException upon concurrent annotation model changes
267
Position pos= model.getPosition(annot);
268                     if (pos != null) {
269                         // may throw an IndexOutOfBoundsException upon concurrent document modification
270
int startLine= document.getLineOfOffset(pos.getOffset());
271                         if (startLine == currLine && JavaCorrectionProcessor.hasCorrections(annot)) {
272                             return true;
273                         }
274                     }
275                 }
276             }
277         } catch (BadLocationException e) {
278             // ignore
279
} catch (IndexOutOfBoundsException JavaDoc e) {
280             // concurrent modification - too bad, ignore
281
} catch (ConcurrentModificationException JavaDoc e) {
282             // concurrent modification - too bad, ignore
283
}
284         return false;
285     }
286
287
288 }
289
Popular Tags