KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > javaeditor > JavaEditor


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.javaeditor;
12
13 import com.ibm.icu.text.BreakIterator;
14
15 import java.text.CharacterIterator JavaDoc;
16 import java.util.ArrayList JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Map JavaDoc;
21
22 import org.eclipse.core.commands.operations.IOperationApprover;
23 import org.eclipse.core.commands.operations.IUndoContext;
24
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IProgressMonitor;
27 import org.eclipse.core.runtime.IStatus;
28 import org.eclipse.core.runtime.ListenerList;
29 import org.eclipse.core.runtime.NullProgressMonitor;
30 import org.eclipse.core.runtime.Status;
31 import org.eclipse.core.runtime.jobs.Job;
32 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
33 import org.eclipse.core.runtime.preferences.IScopeContext;
34
35 import org.eclipse.core.resources.IResource;
36 import org.eclipse.core.resources.ProjectScope;
37
38 import org.eclipse.swt.SWT;
39 import org.eclipse.swt.custom.ST;
40 import org.eclipse.swt.custom.StyledText;
41 import org.eclipse.swt.graphics.Image;
42 import org.eclipse.swt.graphics.Point;
43 import org.eclipse.swt.widgets.Composite;
44 import org.eclipse.swt.widgets.Display;
45 import org.eclipse.swt.widgets.Shell;
46
47 import org.eclipse.help.IContextProvider;
48
49 import org.eclipse.jface.action.Action;
50 import org.eclipse.jface.action.GroupMarker;
51 import org.eclipse.jface.action.IAction;
52 import org.eclipse.jface.action.IMenuManager;
53 import org.eclipse.jface.action.MenuManager;
54 import org.eclipse.jface.preference.IPreferenceStore;
55 import org.eclipse.jface.util.IPropertyChangeListener;
56 import org.eclipse.jface.util.PropertyChangeEvent;
57 import org.eclipse.jface.viewers.DoubleClickEvent;
58 import org.eclipse.jface.viewers.IDoubleClickListener;
59 import org.eclipse.jface.viewers.IPostSelectionProvider;
60 import org.eclipse.jface.viewers.ISelection;
61 import org.eclipse.jface.viewers.ISelectionChangedListener;
62 import org.eclipse.jface.viewers.ISelectionProvider;
63 import org.eclipse.jface.viewers.IStructuredSelection;
64 import org.eclipse.jface.viewers.SelectionChangedEvent;
65 import org.eclipse.jface.viewers.StructuredSelection;
66
67 import org.eclipse.jface.text.BadLocationException;
68 import org.eclipse.jface.text.DocumentEvent;
69 import org.eclipse.jface.text.IDocument;
70 import org.eclipse.jface.text.IDocumentExtension4;
71 import org.eclipse.jface.text.IDocumentListener;
72 import org.eclipse.jface.text.IInformationControl;
73 import org.eclipse.jface.text.IInformationControlCreator;
74 import org.eclipse.jface.text.IRegion;
75 import org.eclipse.jface.text.ISelectionValidator;
76 import org.eclipse.jface.text.ISynchronizable;
77 import org.eclipse.jface.text.ITextHover;
78 import org.eclipse.jface.text.ITextInputListener;
79 import org.eclipse.jface.text.ITextOperationTarget;
80 import org.eclipse.jface.text.ITextSelection;
81 import org.eclipse.jface.text.ITextViewer;
82 import org.eclipse.jface.text.ITextViewerExtension2;
83 import org.eclipse.jface.text.ITextViewerExtension5;
84 import org.eclipse.jface.text.Position;
85 import org.eclipse.jface.text.Region;
86 import org.eclipse.jface.text.TextUtilities;
87 import org.eclipse.jface.text.link.LinkedModeModel;
88 import org.eclipse.jface.text.link.LinkedPosition;
89 import org.eclipse.jface.text.reconciler.IReconciler;
90 import org.eclipse.jface.text.source.Annotation;
91 import org.eclipse.jface.text.source.AnnotationRulerColumn;
92 import org.eclipse.jface.text.source.CompositeRuler;
93 import org.eclipse.jface.text.source.IAnnotationModel;
94 import org.eclipse.jface.text.source.IAnnotationModelExtension;
95 import org.eclipse.jface.text.source.ICharacterPairMatcher;
96 import org.eclipse.jface.text.source.IOverviewRuler;
97 import org.eclipse.jface.text.source.ISourceViewer;
98 import org.eclipse.jface.text.source.ISourceViewerExtension2;
99 import org.eclipse.jface.text.source.IVerticalRuler;
100 import org.eclipse.jface.text.source.IVerticalRulerColumn;
101 import org.eclipse.jface.text.source.LineChangeHover;
102 import org.eclipse.jface.text.source.SourceViewerConfiguration;
103 import org.eclipse.jface.text.source.projection.ProjectionSupport;
104 import org.eclipse.jface.text.source.projection.ProjectionViewer;
105
106 import org.eclipse.ui.IEditorInput;
107 import org.eclipse.ui.IEditorPart;
108 import org.eclipse.ui.IPageLayout;
109 import org.eclipse.ui.IPartListener2;
110 import org.eclipse.ui.IPartService;
111 import org.eclipse.ui.ISelectionListener;
112 import org.eclipse.ui.IWindowListener;
113 import org.eclipse.ui.IWorkbenchPage;
114 import org.eclipse.ui.IWorkbenchPart;
115 import org.eclipse.ui.IWorkbenchPartReference;
116 import org.eclipse.ui.IWorkbenchPartSite;
117 import org.eclipse.ui.IWorkbenchWindow;
118 import org.eclipse.ui.PlatformUI;
119 import org.eclipse.ui.actions.ActionContext;
120 import org.eclipse.ui.actions.ActionGroup;
121 import org.eclipse.ui.operations.NonLocalUndoUserApprover;
122 import org.eclipse.ui.part.IShowInSource;
123 import org.eclipse.ui.part.IShowInTargetList;
124 import org.eclipse.ui.part.ShowInContext;
125 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
126 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
127 import org.eclipse.ui.texteditor.AnnotationPreference;
128 import org.eclipse.ui.texteditor.ChainedPreferenceStore;
129 import org.eclipse.ui.texteditor.IDocumentProvider;
130 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
131 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
132 import org.eclipse.ui.texteditor.IUpdate;
133 import org.eclipse.ui.texteditor.MarkerAnnotation;
134 import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
135 import org.eclipse.ui.texteditor.TextNavigationAction;
136 import org.eclipse.ui.texteditor.TextOperationAction;
137
138 import org.eclipse.ui.editors.text.DefaultEncodingSupport;
139 import org.eclipse.ui.editors.text.EditorsUI;
140 import org.eclipse.ui.editors.text.IEncodingSupport;
141
142 import org.eclipse.ui.views.contentoutline.ContentOutline;
143 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
144
145 import org.eclipse.jdt.core.IClassFile;
146 import org.eclipse.jdt.core.ICompilationUnit;
147 import org.eclipse.jdt.core.IImportContainer;
148 import org.eclipse.jdt.core.IImportDeclaration;
149 import org.eclipse.jdt.core.IJavaElement;
150 import org.eclipse.jdt.core.IJavaProject;
151 import org.eclipse.jdt.core.ILocalVariable;
152 import org.eclipse.jdt.core.IMember;
153 import org.eclipse.jdt.core.IPackageDeclaration;
154 import org.eclipse.jdt.core.ISourceRange;
155 import org.eclipse.jdt.core.ISourceReference;
156 import org.eclipse.jdt.core.ITypeParameter;
157 import org.eclipse.jdt.core.JavaCore;
158 import org.eclipse.jdt.core.JavaModelException;
159 import org.eclipse.jdt.core.dom.ASTNode;
160 import org.eclipse.jdt.core.dom.CompilationUnit;
161 import org.eclipse.jdt.core.dom.IBinding;
162 import org.eclipse.jdt.core.dom.IVariableBinding;
163 import org.eclipse.jdt.core.dom.Name;
164 import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
165 import org.eclipse.jdt.core.util.IModifierConstants;
166
167 import org.eclipse.jdt.internal.corext.dom.NodeFinder;
168 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
169
170 import org.eclipse.jdt.ui.IContextMenuConstants;
171 import org.eclipse.jdt.ui.JavaUI;
172 import org.eclipse.jdt.ui.PreferenceConstants;
173 import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds;
174 import org.eclipse.jdt.ui.actions.JavaSearchActionGroup;
175 import org.eclipse.jdt.ui.actions.OpenEditorActionGroup;
176 import org.eclipse.jdt.ui.actions.OpenViewActionGroup;
177 import org.eclipse.jdt.ui.actions.ShowInPackageViewAction;
178 import org.eclipse.jdt.ui.text.IJavaPartitions;
179 import org.eclipse.jdt.ui.text.JavaSourceViewerConfiguration;
180 import org.eclipse.jdt.ui.text.JavaTextTools;
181 import org.eclipse.jdt.ui.text.folding.IJavaFoldingStructureProvider;
182 import org.eclipse.jdt.ui.text.folding.IJavaFoldingStructureProviderExtension;
183
184 import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
185 import org.eclipse.jdt.internal.ui.JavaPlugin;
186 import org.eclipse.jdt.internal.ui.actions.CompositeActionGroup;
187 import org.eclipse.jdt.internal.ui.actions.CopyQualifiedNameAction;
188 import org.eclipse.jdt.internal.ui.actions.FoldingActionGroup;
189 import org.eclipse.jdt.internal.ui.actions.SelectionConverter;
190 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.GoToNextPreviousMemberAction;
191 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.SelectionHistory;
192 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectEnclosingAction;
193 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectHistoryAction;
194 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectNextAction;
195 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectPreviousAction;
196 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectionAction;
197 import org.eclipse.jdt.internal.ui.search.BreakContinueTargetFinder;
198 import org.eclipse.jdt.internal.ui.search.ExceptionOccurrencesFinder;
199 import org.eclipse.jdt.internal.ui.search.ImplementOccurrencesFinder;
200 import org.eclipse.jdt.internal.ui.search.MethodExitsFinder;
201 import org.eclipse.jdt.internal.ui.search.OccurrencesFinder;
202 import org.eclipse.jdt.internal.ui.text.DocumentCharacterIterator;
203 import org.eclipse.jdt.internal.ui.text.JavaChangeHover;
204 import org.eclipse.jdt.internal.ui.text.JavaPairMatcher;
205 import org.eclipse.jdt.internal.ui.text.JavaWordFinder;
206 import org.eclipse.jdt.internal.ui.text.JavaWordIterator;
207 import org.eclipse.jdt.internal.ui.text.PreferencesAdapter;
208 import org.eclipse.jdt.internal.ui.text.java.hover.JavaExpandHover;
209 import org.eclipse.jdt.internal.ui.text.java.hover.SourceViewerInformationControl;
210 import org.eclipse.jdt.internal.ui.util.JavaUIHelp;
211 import org.eclipse.jdt.internal.ui.viewsupport.ISelectionListenerWithAST;
212 import org.eclipse.jdt.internal.ui.viewsupport.IViewPartInputProvider;
213 import org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager;
214
215 import org.osgi.service.prefs.BackingStoreException;
216
217 /**
218  * Java specific text editor.
219  */

220 public abstract class JavaEditor extends AbstractDecoratedTextEditor implements IViewPartInputProvider {
221
222     /**
223      * Internal implementation class for a change listener.
224      * @since 3.0
225      */

226     protected abstract class AbstractSelectionChangedListener implements ISelectionChangedListener {
227
228         /**
229          * Installs this selection changed listener with the given selection provider. If
230          * the selection provider is a post selection provider, post selection changed
231          * events are the preferred choice, otherwise normal selection changed events
232          * are requested.
233          *
234          * @param selectionProvider
235          */

236         public void install(ISelectionProvider selectionProvider) {
237             if (selectionProvider == null)
238                 return;
239
240             if (selectionProvider instanceof IPostSelectionProvider) {
241                 IPostSelectionProvider provider= (IPostSelectionProvider) selectionProvider;
242                 provider.addPostSelectionChangedListener(this);
243             } else {
244                 selectionProvider.addSelectionChangedListener(this);
245             }
246         }
247
248         /**
249          * Removes this selection changed listener from the given selection provider.
250          *
251          * @param selectionProvider the selection provider
252          */

253         public void uninstall(ISelectionProvider selectionProvider) {
254             if (selectionProvider == null)
255                 return;
256
257             if (selectionProvider instanceof IPostSelectionProvider) {
258                 IPostSelectionProvider provider= (IPostSelectionProvider) selectionProvider;
259                 provider.removePostSelectionChangedListener(this);
260             } else {
261                 selectionProvider.removeSelectionChangedListener(this);
262             }
263         }
264     }
265
266     /**
267      * Updates the Java outline page selection and this editor's range indicator.
268      *
269      * @since 3.0
270      */

271     private class EditorSelectionChangedListener extends AbstractSelectionChangedListener {
272
273         /*
274          * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
275          */

276         public void selectionChanged(SelectionChangedEvent event) {
277             // XXX: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=56161
278
JavaEditor.this.selectionChanged();
279         }
280     }
281
282     /**
283      * Updates the selection in the editor's widget with the selection of the outline page.
284      */

285     class OutlineSelectionChangedListener extends AbstractSelectionChangedListener {
286         public void selectionChanged(SelectionChangedEvent event) {
287             doSelectionChanged(event);
288         }
289     }
290
291
292     /**
293      * Adapts an options {@link IEclipsePreferences} to {@link org.eclipse.jface.preference.IPreferenceStore}.
294      * <p>
295      * This preference store is read-only i.e. write access
296      * throws an {@link java.lang.UnsupportedOperationException}.
297      * </p>
298      *
299      * @since 3.1
300      */

301     private static class EclipsePreferencesAdapter implements IPreferenceStore {
302
303         /**
304          * Preference change listener. Listens for events preferences
305          * fires a {@link org.eclipse.jface.util.PropertyChangeEvent}
306          * on this adapter with arguments from the received event.
307          */

308         private class PreferenceChangeListener implements IEclipsePreferences.IPreferenceChangeListener {
309
310             /**
311              * {@inheritDoc}
312              */

313             public void preferenceChange(final IEclipsePreferences.PreferenceChangeEvent event) {
314                 if (Display.getCurrent() == null) {
315                     Display.getDefault().asyncExec(new Runnable JavaDoc() {
316                         public void run() {
317                             firePropertyChangeEvent(event.getKey(), event.getOldValue(), event.getNewValue());
318                         }
319                     });
320                 } else {
321                     firePropertyChangeEvent(event.getKey(), event.getOldValue(), event.getNewValue());
322                 }
323             }
324         }
325
326         /** Listeners on on this adapter */
327         private ListenerList fListeners= new ListenerList(ListenerList.IDENTITY);
328
329         /** Listener on the node */
330         private IEclipsePreferences.IPreferenceChangeListener fListener= new PreferenceChangeListener();
331
332         /** wrapped node */
333         private final IScopeContext fContext;
334         private final String JavaDoc fQualifier;
335
336         /**
337          * Initialize with the node to wrap
338          *
339          * @param context the context to access
340          * @param qualifier the qualifier
341          */

342         public EclipsePreferencesAdapter(IScopeContext context, String JavaDoc qualifier) {
343             fContext= context;
344             fQualifier= qualifier;
345         }
346
347         private IEclipsePreferences getNode() {
348             return fContext.getNode(fQualifier);
349         }
350
351         /**
352          * {@inheritDoc}
353          */

354         public void addPropertyChangeListener(IPropertyChangeListener listener) {
355             if (fListeners.size() == 0)
356                 getNode().addPreferenceChangeListener(fListener);
357             fListeners.add(listener);
358         }
359
360         /**
361          * {@inheritDoc}
362          */

363         public void removePropertyChangeListener(IPropertyChangeListener listener) {
364             fListeners.remove(listener);
365             if (fListeners.size() == 0) {
366                 getNode().removePreferenceChangeListener(fListener);
367             }
368         }
369
370         /**
371          * {@inheritDoc}
372          */

373         public boolean contains(String JavaDoc name) {
374             return getNode().get(name, null) != null;
375         }
376
377         /**
378          * {@inheritDoc}
379          */

380         public void firePropertyChangeEvent(String JavaDoc name, Object JavaDoc oldValue, Object JavaDoc newValue) {
381             PropertyChangeEvent event= new PropertyChangeEvent(this, name, oldValue, newValue);
382             Object JavaDoc[] listeners= fListeners.getListeners();
383             for (int i= 0; i < listeners.length; i++)
384                 ((IPropertyChangeListener) listeners[i]).propertyChange(event);
385         }
386
387         /**
388          * {@inheritDoc}
389          */

390         public boolean getBoolean(String JavaDoc name) {
391             return getNode().getBoolean(name, BOOLEAN_DEFAULT_DEFAULT);
392         }
393
394         /**
395          * {@inheritDoc}
396          */

397         public boolean getDefaultBoolean(String JavaDoc name) {
398             return BOOLEAN_DEFAULT_DEFAULT;
399         }
400
401         /**
402          * {@inheritDoc}
403          */

404         public double getDefaultDouble(String JavaDoc name) {
405             return DOUBLE_DEFAULT_DEFAULT;
406         }
407
408         /**
409          * {@inheritDoc}
410          */

411         public float getDefaultFloat(String JavaDoc name) {
412             return FLOAT_DEFAULT_DEFAULT;
413         }
414
415         /**
416          * {@inheritDoc}
417          */

418         public int getDefaultInt(String JavaDoc name) {
419             return INT_DEFAULT_DEFAULT;
420         }
421
422         /**
423          * {@inheritDoc}
424          */

425         public long getDefaultLong(String JavaDoc name) {
426             return LONG_DEFAULT_DEFAULT;
427         }
428
429         /**
430          * {@inheritDoc}
431          */

432         public String JavaDoc getDefaultString(String JavaDoc name) {
433             return STRING_DEFAULT_DEFAULT;
434         }
435
436         /**
437          * {@inheritDoc}
438          */

439         public double getDouble(String JavaDoc name) {
440             return getNode().getDouble(name, DOUBLE_DEFAULT_DEFAULT);
441         }
442
443         /**
444          * {@inheritDoc}
445          */

446         public float getFloat(String JavaDoc name) {
447             return getNode().getFloat(name, FLOAT_DEFAULT_DEFAULT);
448         }
449
450         /**
451          * {@inheritDoc}
452          */

453         public int getInt(String JavaDoc name) {
454             return getNode().getInt(name, INT_DEFAULT_DEFAULT);
455         }
456
457         /**
458          * {@inheritDoc}
459          */

460         public long getLong(String JavaDoc name) {
461             return getNode().getLong(name, LONG_DEFAULT_DEFAULT);
462         }
463
464         /**
465          * {@inheritDoc}
466          */

467         public String JavaDoc getString(String JavaDoc name) {
468             return getNode().get(name, STRING_DEFAULT_DEFAULT);
469         }
470
471         /**
472          * {@inheritDoc}
473          */

474         public boolean isDefault(String JavaDoc name) {
475             return false;
476         }
477
478         /**
479          * {@inheritDoc}
480          */

481         public boolean needsSaving() {
482             try {
483                 return getNode().keys().length > 0;
484             } catch (BackingStoreException e) {
485                 // ignore
486
}
487             return true;
488         }
489
490         /**
491          * {@inheritDoc}
492          */

493         public void putValue(String JavaDoc name, String JavaDoc value) {
494             throw new UnsupportedOperationException JavaDoc();
495         }
496
497         /**
498          * {@inheritDoc}
499          */

500         public void setDefault(String JavaDoc name, double value) {
501             throw new UnsupportedOperationException JavaDoc();
502         }
503
504         /**
505          * {@inheritDoc}
506          */

507         public void setDefault(String JavaDoc name, float value) {
508             throw new UnsupportedOperationException JavaDoc();
509         }
510
511         /**
512          * {@inheritDoc}
513          */

514         public void setDefault(String JavaDoc name, int value) {
515             throw new UnsupportedOperationException JavaDoc();
516         }
517
518         /**
519          * {@inheritDoc}
520          */

521         public void setDefault(String JavaDoc name, long value) {
522             throw new UnsupportedOperationException JavaDoc();
523         }
524
525         /**
526          * {@inheritDoc}
527          */

528         public void setDefault(String JavaDoc name, String JavaDoc defaultObject) {
529             throw new UnsupportedOperationException JavaDoc();
530         }
531
532         /**
533          * {@inheritDoc}
534          */

535         public void setDefault(String JavaDoc name, boolean value) {
536             throw new UnsupportedOperationException JavaDoc();
537         }
538
539         /**
540          * {@inheritDoc}
541          */

542         public void setToDefault(String JavaDoc name) {
543             throw new UnsupportedOperationException JavaDoc();
544         }
545
546         /**
547          * {@inheritDoc}
548          */

549         public void setValue(String JavaDoc name, double value) {
550             throw new UnsupportedOperationException JavaDoc();
551         }
552
553         /**
554          * {@inheritDoc}
555          */

556         public void setValue(String JavaDoc name, float value) {
557             throw new UnsupportedOperationException JavaDoc();
558         }
559
560         /**
561          * {@inheritDoc}
562          */

563         public void setValue(String JavaDoc name, int value) {
564             throw new UnsupportedOperationException JavaDoc();
565         }
566
567         /**
568          * {@inheritDoc}
569          */

570         public void setValue(String JavaDoc name, long value) {
571             throw new UnsupportedOperationException JavaDoc();
572         }
573
574         /**
575          * {@inheritDoc}
576          */

577         public void setValue(String JavaDoc name, String JavaDoc value) {
578             throw new UnsupportedOperationException JavaDoc();
579         }
580
581         /**
582          * {@inheritDoc}
583          */

584         public void setValue(String JavaDoc name, boolean value) {
585             throw new UnsupportedOperationException JavaDoc();
586         }
587
588     }
589
590
591     /**
592      * Cancels the occurrences finder job upon document changes.
593      *
594      * @since 3.0
595      */

596     class OccurrencesFinderJobCanceler implements IDocumentListener, ITextInputListener {
597
598         public void install() {
599             ISourceViewer sourceViewer= getSourceViewer();
600             if (sourceViewer == null)
601                 return;
602
603             StyledText text= sourceViewer.getTextWidget();
604             if (text == null || text.isDisposed())
605                 return;
606
607             sourceViewer.addTextInputListener(this);
608
609             IDocument document= sourceViewer.getDocument();
610             if (document != null)
611                 document.addDocumentListener(this);
612         }
613
614         public void uninstall() {
615             ISourceViewer sourceViewer= getSourceViewer();
616             if (sourceViewer != null)
617                 sourceViewer.removeTextInputListener(this);
618
619             IDocumentProvider documentProvider= getDocumentProvider();
620             if (documentProvider != null) {
621                 IDocument document= documentProvider.getDocument(getEditorInput());
622                 if (document != null)
623                     document.removeDocumentListener(this);
624             }
625         }
626
627
628         /*
629          * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
630          */

631         public void documentAboutToBeChanged(DocumentEvent event) {
632             if (fOccurrencesFinderJob != null)
633                 fOccurrencesFinderJob.doCancel();
634         }
635
636         /*
637          * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
638          */

639         public void documentChanged(DocumentEvent event) {
640         }
641
642         /*
643          * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
644          */

645         public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
646             if (oldInput == null)
647                 return;
648
649             oldInput.removeDocumentListener(this);
650         }
651
652         /*
653          * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
654          */

655         public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
656             if (newInput == null)
657                 return;
658             newInput.addDocumentListener(this);
659         }
660     }
661
662     /**
663      * This action implements smart home.
664      *
665      * Instead of going to the start of a line it does the following:
666      *
667      * - if smart home/end is enabled and the caret is after the line's first non-whitespace then the caret is moved directly before it, taking JavaDoc and multi-line comments into account.
668      * - if the caret is before the line's first non-whitespace the caret is moved to the beginning of the line
669      * - if the caret is at the beginning of the line see first case.
670      *
671      * @since 3.0
672      */

673     protected class SmartLineStartAction extends LineStartAction {
674
675         /**
676          * Creates a new smart line start action
677          *
678          * @param textWidget the styled text widget
679          * @param doSelect a boolean flag which tells if the text up to the beginning of the line should be selected
680          */

681         public SmartLineStartAction(final StyledText textWidget, final boolean doSelect) {
682             super(textWidget, doSelect);
683         }
684
685         /*
686          * @see org.eclipse.ui.texteditor.AbstractTextEditor.LineStartAction#getLineStartPosition(java.lang.String, int, java.lang.String)
687          */

688         protected int getLineStartPosition(final IDocument document, final String JavaDoc line, final int length, final int offset) {
689
690             String JavaDoc type= IDocument.DEFAULT_CONTENT_TYPE;
691             try {
692                 type= TextUtilities.getContentType(document, IJavaPartitions.JAVA_PARTITIONING, offset, true);
693             } catch (BadLocationException exception) {
694                 // Should not happen
695
}
696
697             int index= super.getLineStartPosition(document, line, length, offset);
698             if (type.equals(IJavaPartitions.JAVA_DOC) || type.equals(IJavaPartitions.JAVA_MULTI_LINE_COMMENT)) {
699                 if (index < length - 1 && line.charAt(index) == '*' && line.charAt(index + 1) != '/') {
700                     do {
701                         ++index;
702                     } while (index < length && Character.isWhitespace(line.charAt(index)));
703                 }
704             } else {
705                 if (index < length - 1 && line.charAt(index) == '/' && line.charAt(index + 1) == '/') {
706                     index++;
707                     do {
708                         ++index;
709                     } while (index < length && Character.isWhitespace(line.charAt(index)));
710                 }
711             }
712             return index;
713         }
714     }
715
716     /**
717      * Text navigation action to navigate to the next sub-word.
718      *
719      * @since 3.0
720      */

721     protected abstract class NextSubWordAction extends TextNavigationAction {
722
723         protected JavaWordIterator fIterator= new JavaWordIterator();
724
725         /**
726          * Creates a new next sub-word action.
727          *
728          * @param code Action code for the default operation. Must be an action code from @see org.eclipse.swt.custom.ST.
729          */

730         protected NextSubWordAction(int code) {
731             super(getSourceViewer().getTextWidget(), code);
732         }
733
734         /*
735          * @see org.eclipse.jface.action.IAction#run()
736          */

737         public void run() {
738             // Check whether we are in a java code partition and the preference is enabled
739
final IPreferenceStore store= getPreferenceStore();
740             if (!store.getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) {
741                 super.run();
742                 return;
743             }
744
745             final ISourceViewer viewer= getSourceViewer();
746             final IDocument document= viewer.getDocument();
747             fIterator.setText((CharacterIterator JavaDoc) new DocumentCharacterIterator(document));
748             int position= widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset());
749             if (position == -1)
750                 return;
751
752             int next= findNextPosition(position);
753             if (next != BreakIterator.DONE) {
754                 setCaretPosition(next);
755                 getTextWidget().showSelection();
756                 fireSelectionChanged();
757             }
758
759         }
760
761         /**
762          * Finds the next position after the given position.
763          *
764          * @param position the current position
765          * @return the next position
766          */

767         protected int findNextPosition(int position) {
768             ISourceViewer viewer= getSourceViewer();
769             int widget= -1;
770             int next= position;
771             while (next != BreakIterator.DONE && widget == -1) { // TODO: optimize
772
next= fIterator.following(next);
773                 if (next != BreakIterator.DONE)
774                     widget= modelOffset2WidgetOffset(viewer, next);
775             }
776             
777             IDocument document= viewer.getDocument();
778             LinkedModeModel model= LinkedModeModel.getModel(document, position);
779             if (model != null) {
780                 LinkedPosition linkedPosition= model.findPosition(new LinkedPosition(document, position, 0));
781                 if (linkedPosition != null) {
782                     int linkedPositionEnd= linkedPosition.getOffset() + linkedPosition.getLength();
783                     if (position != linkedPositionEnd && linkedPositionEnd < next)
784                         next= linkedPositionEnd;
785                 } else {
786                     LinkedPosition nextLinkedPosition= model.findPosition(new LinkedPosition(document, next, 0));
787                     if (nextLinkedPosition != null) {
788                         int nextLinkedPositionOffset= nextLinkedPosition.getOffset();
789                         if (position != nextLinkedPositionOffset && nextLinkedPositionOffset < next)
790                             next= nextLinkedPositionOffset;
791                     }
792                 }
793             }
794             
795             return next;
796         }
797
798         /**
799          * Sets the caret position to the sub-word boundary given with <code>position</code>.
800          *
801          * @param position Position where the action should move the caret
802          */

803         protected abstract void setCaretPosition(int position);
804     }
805
806     /**
807      * Text navigation action to navigate to the next sub-word.
808      *
809      * @since 3.0
810      */

811     protected class NavigateNextSubWordAction extends NextSubWordAction {
812
813         /**
814          * Creates a new navigate next sub-word action.
815          */

816         public NavigateNextSubWordAction() {
817             super(ST.WORD_NEXT);
818         }
819
820         /*
821          * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
822          */

823         protected void setCaretPosition(final int position) {
824             getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position));
825         }
826     }
827
828     /**
829      * Text operation action to delete the next sub-word.
830      *
831      * @since 3.0
832      */

833     protected class DeleteNextSubWordAction extends NextSubWordAction implements IUpdate {
834
835         /**
836          * Creates a new delete next sub-word action.
837          */

838         public DeleteNextSubWordAction() {
839             super(ST.DELETE_WORD_NEXT);
840         }
841
842         /*
843          * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
844          */

845         protected void setCaretPosition(final int position) {
846             if (!validateEditorInputState())
847                 return;
848
849             final ISourceViewer viewer= getSourceViewer();
850             final int caret, length;
851             Point selection= viewer.getSelectedRange();
852             if (selection.y != 0) {
853                 caret= selection.x;
854                 length= selection.y;
855             } else {
856                 caret= widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset());
857                 length= position - caret;
858             }
859
860             try {
861                 viewer.getDocument().replace(caret, length, ""); //$NON-NLS-1$
862
} catch (BadLocationException exception) {
863                 // Should not happen
864
}
865         }
866
867         /*
868          * @see org.eclipse.ui.texteditor.IUpdate#update()
869          */

870         public void update() {
871             setEnabled(isEditorInputModifiable());
872         }
873     }
874
875     /**
876      * Text operation action to select the next sub-word.
877      *
878      * @since 3.0
879      */

880     protected class SelectNextSubWordAction extends NextSubWordAction {
881
882         /**
883          * Creates a new select next sub-word action.
884          */

885         public SelectNextSubWordAction() {
886             super(ST.SELECT_WORD_NEXT);
887         }
888
889         /*
890          * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
891          */

892         protected void setCaretPosition(final int position) {
893             final ISourceViewer viewer= getSourceViewer();
894
895             final StyledText text= viewer.getTextWidget();
896             if (text != null && !text.isDisposed()) {
897
898                 final Point selection= text.getSelection();
899                 final int caret= text.getCaretOffset();
900                 final int offset= modelOffset2WidgetOffset(viewer, position);
901
902                 if (caret == selection.x)
903                     text.setSelectionRange(selection.y, offset - selection.y);
904                 else
905                     text.setSelectionRange(selection.x, offset - selection.x);
906             }
907         }
908     }
909
910     /**
911      * Text navigation action to navigate to the previous sub-word.
912      *
913      * @since 3.0
914      */

915     protected abstract class PreviousSubWordAction extends TextNavigationAction {
916
917         protected JavaWordIterator fIterator= new JavaWordIterator();
918
919         /**
920          * Creates a new previous sub-word action.
921          *
922          * @param code Action code for the default operation. Must be an action code from @see org.eclipse.swt.custom.ST.
923          */

924         protected PreviousSubWordAction(final int code) {
925             super(getSourceViewer().getTextWidget(), code);
926         }
927
928         /*
929          * @see org.eclipse.jface.action.IAction#run()
930          */

931         public void run() {
932             // Check whether we are in a java code partition and the preference is enabled
933
final IPreferenceStore store= getPreferenceStore();
934             if (!store.getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) {
935                 super.run();
936                 return;
937             }
938
939             final ISourceViewer viewer= getSourceViewer();
940             final IDocument document= viewer.getDocument();
941             fIterator.setText((CharacterIterator JavaDoc) new DocumentCharacterIterator(document));
942             int position= widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset());
943             if (position == -1)
944                 return;
945
946             int previous= findPreviousPosition(position);
947             if (previous != BreakIterator.DONE) {
948                 setCaretPosition(previous);
949                 getTextWidget().showSelection();
950                 fireSelectionChanged();
951             }
952
953         }
954
955         /**
956          * Finds the previous position before the given position.
957          *
958          * @param position the current position
959          * @return the previous position
960          */

961         protected int findPreviousPosition(int position) {
962             ISourceViewer viewer= getSourceViewer();
963             int widget= -1;
964             int previous= position;
965             while (previous != BreakIterator.DONE && widget == -1) { // TODO: optimize
966
previous= fIterator.preceding(previous);
967                 if (previous != BreakIterator.DONE)
968                     widget= modelOffset2WidgetOffset(viewer, previous);
969             }
970             
971             IDocument document= viewer.getDocument();
972             LinkedModeModel model= LinkedModeModel.getModel(document, position);
973             if (model != null) {
974                 LinkedPosition linkedPosition= model.findPosition(new LinkedPosition(document, position, 0));
975                 if (linkedPosition != null) {
976                     int linkedPositionOffset= linkedPosition.getOffset();
977                     if (position != linkedPositionOffset && previous < linkedPositionOffset)
978                         previous= linkedPositionOffset;
979                 } else {
980                     LinkedPosition previousLinkedPosition= model.findPosition(new LinkedPosition(document, previous, 0));
981                     if (previousLinkedPosition != null) {
982                         int previousLinkedPositionEnd= previousLinkedPosition.getOffset() + previousLinkedPosition.getLength();
983                         if (position != previousLinkedPositionEnd && previous < previousLinkedPositionEnd)
984                             previous= previousLinkedPositionEnd;
985                     }
986                 }
987             }
988             
989             return previous;
990         }
991
992         /**
993          * Sets the caret position to the sub-word boundary given with <code>position</code>.
994          *
995          * @param position Position where the action should move the caret
996          */

997         protected abstract void setCaretPosition(int position);
998     }
999
1000    /**
1001     * Text navigation action to navigate to the previous sub-word.
1002     *
1003     * @since 3.0
1004     */

1005    protected class NavigatePreviousSubWordAction extends PreviousSubWordAction {
1006
1007        /**
1008         * Creates a new navigate previous sub-word action.
1009         */

1010        public NavigatePreviousSubWordAction() {
1011            super(ST.WORD_PREVIOUS);
1012        }
1013
1014        /*
1015         * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
1016         */

1017        protected void setCaretPosition(final int position) {
1018            getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position));
1019        }
1020    }
1021
1022    /**
1023     * Text operation action to delete the previous sub-word.
1024     *
1025     * @since 3.0
1026     */

1027    protected class DeletePreviousSubWordAction extends PreviousSubWordAction implements IUpdate {
1028
1029        /**
1030         * Creates a new delete previous sub-word action.
1031         */

1032        public DeletePreviousSubWordAction() {
1033            super(ST.DELETE_WORD_PREVIOUS);
1034        }
1035
1036        /*
1037         * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
1038         */

1039        protected void setCaretPosition(int position) {
1040            if (!validateEditorInputState())
1041                return;
1042
1043            final int length;
1044            final ISourceViewer viewer= getSourceViewer();
1045            Point selection= viewer.getSelectedRange();
1046            if (selection.y != 0) {
1047                position= selection.x;
1048                length= selection.y;
1049            } else {
1050                length= widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset()) - position;
1051            }
1052
1053            try {
1054                viewer.getDocument().replace(position, length, ""); //$NON-NLS-1$
1055
} catch (BadLocationException exception) {
1056                // Should not happen
1057
}
1058        }
1059
1060        /*
1061         * @see org.eclipse.ui.texteditor.IUpdate#update()
1062         */

1063        public void update() {
1064            setEnabled(isEditorInputModifiable());
1065        }
1066    }
1067
1068    /**
1069     * Text operation action to select the previous sub-word.
1070     *
1071     * @since 3.0
1072     */

1073    protected class SelectPreviousSubWordAction extends PreviousSubWordAction {
1074
1075        /**
1076         * Creates a new select previous sub-word action.
1077         */

1078        public SelectPreviousSubWordAction() {
1079            super(ST.SELECT_WORD_PREVIOUS);
1080        }
1081
1082        /*
1083         * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
1084         */

1085        protected void setCaretPosition(final int position) {
1086            final ISourceViewer viewer= getSourceViewer();
1087
1088            final StyledText text= viewer.getTextWidget();
1089            if (text != null && !text.isDisposed()) {
1090
1091                final Point selection= text.getSelection();
1092                final int caret= text.getCaretOffset();
1093                final int offset= modelOffset2WidgetOffset(viewer, position);
1094
1095                if (caret == selection.x)
1096                    text.setSelectionRange(selection.y, offset - selection.y);
1097                else
1098                    text.setSelectionRange(selection.x, offset - selection.x);
1099            }
1100        }
1101    }
1102
1103    /**
1104     * Format element action to format the enclosing java element.
1105     * <p>
1106     * The format element action works as follows:
1107     * <ul>
1108     * <li>If there is no selection and the caret is positioned on a Java element,
1109     * only this element is formatted. If the element has some accompanying comment,
1110     * then the comment is formatted as well.</li>
1111     * <li>If the selection spans one or more partitions of the document, then all
1112     * partitions covered by the selection are entirely formatted.</li>
1113     * <p>
1114     * Partitions at the end of the selection are not completed, except for comments.
1115     *
1116     * @since 3.0
1117     */

1118    protected class FormatElementAction extends Action implements IUpdate {
1119        
1120        /*
1121         * @since 3.2
1122         */

1123        FormatElementAction() {
1124            setEnabled(isEditorInputModifiable());
1125        }
1126
1127        /*
1128         * @see org.eclipse.jface.action.IAction#run()
1129         */

1130        public void run() {
1131
1132            final JavaSourceViewer viewer= (JavaSourceViewer) getSourceViewer();
1133            if (viewer.isEditable()) {
1134
1135                final Point selection= viewer.rememberSelection();
1136                try {
1137                    viewer.setRedraw(false);
1138
1139                    final String JavaDoc type= TextUtilities.getContentType(viewer.getDocument(), IJavaPartitions.JAVA_PARTITIONING, selection.x, true);
1140                    if (type.equals(IDocument.DEFAULT_CONTENT_TYPE) && selection.y == 0) {
1141
1142                        try {
1143                            final IJavaElement element= getElementAt(selection.x, true);
1144                            if (element != null && element.exists()) {
1145
1146                                final int kind= element.getElementType();
1147                                if (kind == IJavaElement.TYPE || kind == IJavaElement.METHOD || kind == IJavaElement.INITIALIZER) {
1148
1149                                    final ISourceReference reference= (ISourceReference)element;
1150                                    final ISourceRange range= reference.getSourceRange();
1151
1152                                    if (range != null) {
1153                                        viewer.setSelectedRange(range.getOffset(), range.getLength());
1154                                        viewer.doOperation(ISourceViewer.FORMAT);
1155                                    }
1156                                }
1157                            }
1158                        } catch (JavaModelException exception) {
1159                            // Should not happen
1160
}
1161                    } else {
1162                        viewer.setSelectedRange(selection.x, 1);
1163                        viewer.doOperation(ISourceViewer.FORMAT);
1164                    }
1165                } catch (BadLocationException exception) {
1166                    // Can not happen
1167
} finally {
1168
1169                    viewer.setRedraw(true);
1170                    viewer.restoreSelection();
1171                }
1172            }
1173        }
1174
1175        /*
1176         * @see org.eclipse.ui.texteditor.IUpdate#update()
1177         * @since 3.2
1178         */

1179        public void update() {
1180            setEnabled(isEditorInputModifiable());
1181        }
1182    }
1183
1184    /**
1185     * Internal activation listener.
1186     * @since 3.0
1187     */

1188    private class ActivationListener implements IWindowListener {
1189
1190        /*
1191         * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow)
1192         * @since 3.1
1193         */

1194        public void windowActivated(IWorkbenchWindow window) {
1195            if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations && isActivePart()) {
1196                fForcedMarkOccurrencesSelection= getSelectionProvider().getSelection();
1197                updateOccurrenceAnnotations((ITextSelection)fForcedMarkOccurrencesSelection, JavaPlugin.getDefault().getASTProvider().getAST(getInputJavaElement(), ASTProvider.WAIT_NO, getProgressMonitor()));
1198            }
1199        }
1200
1201        /*
1202         * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow)
1203         * @since 3.1
1204         */

1205        public void windowDeactivated(IWorkbenchWindow window) {
1206            if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations && isActivePart())
1207                removeOccurrenceAnnotations();
1208        }
1209
1210        /*
1211         * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow)
1212         * @since 3.1
1213         */

1214        public void windowClosed(IWorkbenchWindow window) {
1215        }
1216
1217        /*
1218         * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow)
1219         * @since 3.1
1220         */

1221        public void windowOpened(IWorkbenchWindow window) {
1222        }
1223    }
1224
1225    /**
1226     * Runner that will toggle folding either instantly (if the editor is
1227     * visible) or the next time it becomes visible. If a runner is started when
1228     * there is already one registered, the registered one is canceled as
1229     * toggling folding twice is a no-op.
1230     * <p>
1231     * The access to the fFoldingRunner field is not thread-safe, it is assumed
1232     * that <code>runWhenNextVisible</code> is only called from the UI thread.
1233     * </p>
1234     *
1235     * @since 3.1
1236     */

1237    private final class ToggleFoldingRunner implements IPartListener2 {
1238        /**
1239         * The workbench page we registered the part listener with, or
1240         * <code>null</code>.
1241         */

1242        private IWorkbenchPage fPage;
1243
1244        /**
1245         * Does the actual toggling of projection.
1246         */

1247        private void toggleFolding() {
1248            ISourceViewer sourceViewer= getSourceViewer();
1249            if (sourceViewer instanceof ProjectionViewer) {
1250                ProjectionViewer pv= (ProjectionViewer) sourceViewer;
1251                if (pv.isProjectionMode() != isFoldingEnabled()) {
1252                    if (pv.canDoOperation(ProjectionViewer.TOGGLE))
1253                        pv.doOperation(ProjectionViewer.TOGGLE);
1254                }
1255            }
1256        }
1257
1258        /**
1259         * Makes sure that the editor's folding state is correct the next time
1260         * it becomes visible. If it already is visible, it toggles the folding
1261         * state. If not, it either registers a part listener to toggle folding
1262         * when the editor becomes visible, or cancels an already registered
1263         * runner.
1264         */

1265        public void runWhenNextVisible() {
1266            // if there is one already: toggling twice is the identity
1267
if (fFoldingRunner != null) {
1268                fFoldingRunner.cancel();
1269                return;
1270            }
1271            IWorkbenchPartSite site= getSite();
1272            if (site != null) {
1273                IWorkbenchPage page= site.getPage();
1274                if (!page.isPartVisible(JavaEditor.this)) {
1275                    // if we're not visible - defer until visible
1276
fPage= page;
1277                    fFoldingRunner= this;
1278                    page.addPartListener(this);
1279                    return;
1280                }
1281            }
1282            // we're visible - run now
1283
toggleFolding();
1284        }
1285
1286        /**
1287         * Remove the listener and clear the field.
1288         */

1289        private void cancel() {
1290            if (fPage != null) {
1291                fPage.removePartListener(this);
1292                fPage= null;
1293            }
1294            if (fFoldingRunner == this)
1295                fFoldingRunner= null;
1296        }
1297
1298        /*
1299         * @see org.eclipse.ui.IPartListener2#partVisible(org.eclipse.ui.IWorkbenchPartReference)
1300         */

1301        public void partVisible(IWorkbenchPartReference partRef) {
1302            if (JavaEditor.this.equals(partRef.getPart(false))) {
1303                cancel();
1304                toggleFolding();
1305            }
1306        }
1307
1308        /*
1309         * @see org.eclipse.ui.IPartListener2#partClosed(org.eclipse.ui.IWorkbenchPartReference)
1310         */

1311        public void partClosed(IWorkbenchPartReference partRef) {
1312            if (JavaEditor.this.equals(partRef.getPart(false))) {
1313                cancel();
1314            }
1315        }
1316
1317        public void partActivated(IWorkbenchPartReference partRef) {}
1318        public void partBroughtToTop(IWorkbenchPartReference partRef) {}
1319        public void partDeactivated(IWorkbenchPartReference partRef) {}
1320        public void partOpened(IWorkbenchPartReference partRef) {}
1321        public void partHidden(IWorkbenchPartReference partRef) {}
1322        public void partInputChanged(IWorkbenchPartReference partRef) {}
1323    }
1324
1325    /** Preference key for matching brackets */
1326    protected final static String JavaDoc MATCHING_BRACKETS= PreferenceConstants.EDITOR_MATCHING_BRACKETS;
1327    /** Preference key for matching brackets color */
1328    protected final static String JavaDoc MATCHING_BRACKETS_COLOR= PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
1329
1330    protected final static char[] BRACKETS= { '{', '}', '(', ')', '[', ']', '<', '>' };
1331
1332    /** The outline page */
1333    protected JavaOutlinePage fOutlinePage;
1334    /** Outliner context menu Id */
1335    protected String JavaDoc fOutlinerContextMenuId;
1336    /**
1337     * The editor selection changed listener.
1338     *
1339     * @since 3.0
1340     */

1341    private EditorSelectionChangedListener fEditorSelectionChangedListener;
1342    /** The selection changed listener */
1343    protected AbstractSelectionChangedListener fOutlineSelectionChangedListener= new OutlineSelectionChangedListener();
1344    /** The editor's bracket matcher */
1345    protected JavaPairMatcher fBracketMatcher= new JavaPairMatcher(BRACKETS);
1346    /** This editor's encoding support */
1347    private DefaultEncodingSupport fEncodingSupport;
1348    /** History for structure select action */
1349    private SelectionHistory fSelectionHistory;
1350    protected CompositeActionGroup fActionGroups;
1351
1352    /**
1353     * The action group for folding.
1354     *
1355     * @since 3.0
1356     */

1357    private FoldingActionGroup fFoldingGroup;
1358
1359    private CompositeActionGroup fContextMenuGroup;
1360    /**
1361     * Holds the current occurrence annotations.
1362     * @since 3.0
1363     */

1364    private Annotation[] fOccurrenceAnnotations= null;
1365    /**
1366     * Tells whether all occurrences of the element at the
1367     * current caret location are automatically marked in
1368     * this editor.
1369     * @since 3.0
1370     */

1371    private boolean fMarkOccurrenceAnnotations;
1372    /**
1373     * Tells whether the occurrence annotations are sticky
1374     * i.e. whether they stay even if there's no valid Java
1375     * element at the current caret position.
1376     * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>.
1377     * @since 3.0
1378     */

1379    private boolean fStickyOccurrenceAnnotations;
1380    /**
1381     * Tells whether to mark type occurrences in this editor.
1382     * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>.
1383     * @since 3.0
1384     */

1385    private boolean fMarkTypeOccurrences;
1386    /**
1387     * Tells whether to mark method occurrences in this editor.
1388     * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>.
1389     * @since 3.0
1390     */

1391    private boolean fMarkMethodOccurrences;
1392    /**
1393     * Tells whether to mark constant occurrences in this editor.
1394     * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>.
1395     * @since 3.0
1396     */

1397    private boolean fMarkConstantOccurrences;
1398    /**
1399     * Tells whether to mark field occurrences in this editor.
1400     * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>.
1401     * @since 3.0
1402     */

1403    private boolean fMarkFieldOccurrences;
1404    /**
1405     * Tells whether to mark local variable occurrences in this editor.
1406     * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>.
1407     * @since 3.0
1408     */

1409    private boolean fMarkLocalVariableypeOccurrences;
1410    /**
1411     * Tells whether to mark exception occurrences in this editor.
1412     * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>.
1413     * @since 3.0
1414     */

1415    private boolean fMarkExceptions;
1416    /**
1417     * Tells whether to mark method exits in this editor.
1418     * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>.
1419     * @since 3.0
1420     */

1421    private boolean fMarkMethodExitPoints;
1422    
1423    /**
1424     * Tells whether to mark targets of <code>break</code> and <code>continue</code> statements in this editor.
1425     * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>.
1426     * @since 3.2
1427     */

1428    private boolean fMarkBreakContinueTargets;
1429    
1430    /**
1431     * Tells whether to mark implementors in this editor.
1432     * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>.
1433     * @since 3.1
1434     */

1435    private boolean fMarkImplementors;
1436    /**
1437     * The selection used when forcing occurrence marking
1438     * through code.
1439     * @since 3.0
1440     */

1441    private ISelection fForcedMarkOccurrencesSelection;
1442    /**
1443     * The document modification stamp at the time when the last
1444     * occurrence marking took place.
1445     * @since 3.1
1446     */

1447    private long fMarkOccurrenceModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
1448    /**
1449     * The region of the word under the caret used to when
1450     * computing the current occurrence markings.
1451     * @since 3.1
1452     */

1453    private IRegion fMarkOccurrenceTargetRegion;
1454
1455    /**
1456     * The internal shell activation listener for updating occurrences.
1457     * @since 3.0
1458     */

1459    private ActivationListener fActivationListener= new ActivationListener();
1460    private ISelectionListenerWithAST fPostSelectionListenerWithAST;
1461    private OccurrencesFinderJob fOccurrencesFinderJob;
1462    /** The occurrences finder job canceler */
1463    private OccurrencesFinderJobCanceler fOccurrencesFinderJobCanceler;
1464    /**
1465     * This editor's projection support
1466     * @since 3.0
1467     */

1468    private ProjectionSupport fProjectionSupport;
1469    /**
1470     * This editor's projection model updater
1471     * @since 3.0
1472     */

1473    private IJavaFoldingStructureProvider fProjectionModelUpdater;
1474    /**
1475     * The override and implements indicator manager for this editor.
1476     * @since 3.0
1477     */

1478    protected OverrideIndicatorManager fOverrideIndicatorManager;
1479    /**
1480     * Semantic highlighting manager
1481     * @since 3.0, protected as of 3.3
1482     */

1483    protected SemanticHighlightingManager fSemanticManager;
1484    /**
1485     * The folding runner.
1486     * @since 3.1
1487     */

1488    private ToggleFoldingRunner fFoldingRunner;
1489    
1490    /**
1491     * Tells whether the selection changed event is caused
1492     * by a call to {@link #gotoAnnotation(boolean)}.
1493     *
1494     * @since 3.2
1495     */

1496    private boolean fSelectionChangedViaGotoAnnotation;
1497    /**
1498     * The cached selected range.
1499     *
1500     * @see ITextViewer#getSelectedRange()
1501     * @since 3.3
1502     */

1503    private Point fCachedSelectedRange;
1504
1505
1506    /**
1507     * Returns the most narrow java element including the given offset.
1508     *
1509     * @param offset the offset inside of the requested element
1510     * @return the most narrow java element
1511     */

1512    abstract protected IJavaElement getElementAt(int offset);
1513
1514    /**
1515     * Returns the java element of this editor's input corresponding to the given IJavaElement.
1516     *
1517     * @param element the java element
1518     * @return the corresponding Java element
1519     */

1520    abstract protected IJavaElement getCorrespondingElement(IJavaElement element);
1521
1522    /**
1523     * Default constructor.
1524     */

1525    public JavaEditor() {
1526        super();
1527    }
1528    
1529    /**
1530     * Sets the input of the editor's outline page.
1531     *
1532     * @param page the Java outline page
1533     * @param input the editor input
1534     */

1535    protected void setOutlinePageInput(JavaOutlinePage page, IEditorInput input) {
1536        if (page == null)
1537            return;
1538        
1539        IJavaElement je= getInputJavaElement();
1540        if (je != null && je.exists())
1541            page.setInput(je);
1542        else
1543            page.setInput(null);
1544        
1545    }
1546
1547    /*
1548     * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeKeyBindingScopes()
1549     */

1550    protected void initializeKeyBindingScopes() {
1551        setKeyBindingScopes(new String JavaDoc[] { "org.eclipse.jdt.ui.javaEditorScope" }); //$NON-NLS-1$
1552
}
1553
1554    /*
1555     * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeEditor()
1556     */

1557    protected void initializeEditor() {
1558        IPreferenceStore store= createCombinedPreferenceStore(null);
1559        setPreferenceStore(store);
1560        setSourceViewerConfiguration(createJavaSourceViewerConfiguration());
1561        fMarkOccurrenceAnnotations= store.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES);
1562        fStickyOccurrenceAnnotations= store.getBoolean(PreferenceConstants.EDITOR_STICKY_OCCURRENCES);
1563        fMarkTypeOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES);
1564        fMarkMethodOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES);
1565        fMarkConstantOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES);
1566        fMarkFieldOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES);
1567        fMarkLocalVariableypeOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES);
1568        fMarkExceptions= store.getBoolean(PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES);
1569        fMarkImplementors= store.getBoolean(PreferenceConstants.EDITOR_MARK_IMPLEMENTORS);
1570        fMarkMethodExitPoints= store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS);
1571        fMarkBreakContinueTargets= store.getBoolean(PreferenceConstants.EDITOR_MARK_BREAK_CONTINUE_TARGETS);
1572    }
1573
1574    /**
1575     * Returns a new Java source viewer configuration.
1576     *
1577     * @return a new <code>JavaSourceViewerConfiguration</code>
1578     * @since 3.3
1579     */

1580    protected JavaSourceViewerConfiguration createJavaSourceViewerConfiguration() {
1581        JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools();
1582        return new JavaSourceViewerConfiguration(textTools.getColorManager(), getPreferenceStore(), this, IJavaPartitions.JAVA_PARTITIONING);
1583    }
1584
1585    /*
1586     * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
1587     */

1588    protected final ISourceViewer createSourceViewer(Composite parent, IVerticalRuler verticalRuler, int styles) {
1589
1590        IPreferenceStore store= getPreferenceStore();
1591        ISourceViewer viewer= createJavaSourceViewer(parent, verticalRuler, getOverviewRuler(), isOverviewRulerVisible(), styles, store);
1592
1593        JavaUIHelp.setHelp(this, viewer.getTextWidget(), IJavaHelpContextIds.JAVA_EDITOR);
1594        
1595        JavaSourceViewer javaSourceViewer= null;
1596        if (viewer instanceof JavaSourceViewer)
1597            javaSourceViewer= (JavaSourceViewer)viewer;
1598
1599        /*
1600         * This is a performance optimization to reduce the computation of
1601         * the text presentation triggered by {@link #setVisibleDocument(IDocument)}
1602         */

1603        if (javaSourceViewer != null && isFoldingEnabled() && (store == null || !store.getBoolean(PreferenceConstants.EDITOR_SHOW_SEGMENTS)))
1604            javaSourceViewer.prepareDelayedProjection();
1605        
1606        ProjectionViewer projectionViewer= (ProjectionViewer)viewer;
1607        fProjectionSupport= new ProjectionSupport(projectionViewer, getAnnotationAccess(), getSharedColors());
1608        fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error"); //$NON-NLS-1$
1609
fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.warning"); //$NON-NLS-1$
1610
fProjectionSupport.setHoverControlCreator(new IInformationControlCreator() {
1611            public IInformationControl createInformationControl(Shell shell) {
1612                return new SourceViewerInformationControl(shell, SWT.TOOL | SWT.NO_TRIM | getOrientation(), SWT.NONE, EditorsUI.getTooltipAffordanceString());
1613            }
1614        });
1615        fProjectionSupport.setInformationPresenterControlCreator(new IInformationControlCreator() {
1616            public IInformationControl createInformationControl(Shell shell) {
1617                int shellStyle= SWT.RESIZE | SWT.TOOL | getOrientation();
1618                int style= SWT.V_SCROLL | SWT.H_SCROLL;
1619                return new SourceViewerInformationControl(shell, shellStyle, style);
1620            }
1621        });
1622        fProjectionSupport.install();
1623
1624        fProjectionModelUpdater= JavaPlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider();
1625        if (fProjectionModelUpdater != null)
1626            fProjectionModelUpdater.install(this, projectionViewer);
1627
1628        // ensure source viewer decoration support has been created and configured
1629
getSourceViewerDecorationSupport(viewer);
1630
1631        return viewer;
1632    }
1633
1634    public final ISourceViewer getViewer() {
1635        return getSourceViewer();
1636    }
1637
1638    /*
1639     * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
1640     */

1641    protected ISourceViewer createJavaSourceViewer(Composite parent, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, boolean isOverviewRulerVisible, int styles, IPreferenceStore store) {
1642        return new JavaSourceViewer(parent, verticalRuler, getOverviewRuler(), isOverviewRulerVisible(), styles, store);
1643    }
1644
1645    /*
1646     * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
1647     */

1648    protected boolean affectsTextPresentation(PropertyChangeEvent event) {
1649        return ((JavaSourceViewerConfiguration)getSourceViewerConfiguration()).affectsTextPresentation(event) || super.affectsTextPresentation(event);
1650    }
1651
1652    /**
1653     * Creates and returns the preference store for this Java editor with the given input.
1654     *
1655     * @param input The editor input for which to create the preference store
1656     * @return the preference store for this editor
1657     *
1658     * @since 3.0
1659     */

1660    private IPreferenceStore createCombinedPreferenceStore(IEditorInput input) {
1661        List JavaDoc stores= new ArrayList JavaDoc(3);
1662
1663        IJavaProject project= EditorUtility.getJavaProject(input);
1664        if (project != null) {
1665            stores.add(new EclipsePreferencesAdapter(new ProjectScope(project.getProject()), JavaCore.PLUGIN_ID));
1666        }
1667
1668        stores.add(JavaPlugin.getDefault().getPreferenceStore());
1669        stores.add(new PreferencesAdapter(JavaCore.getPlugin().getPluginPreferences()));
1670        stores.add(EditorsUI.getPreferenceStore());
1671
1672        return new ChainedPreferenceStore((IPreferenceStore[]) stores.toArray(new IPreferenceStore[stores.size()]));
1673    }
1674
1675    /**
1676     * Sets the outliner's context menu ID.
1677     *
1678     * @param menuId the menu ID
1679     */

1680    protected void setOutlinerContextMenuId(String JavaDoc menuId) {
1681        fOutlinerContextMenuId= menuId;
1682    }
1683
1684    /**
1685     * Returns the standard action group of this editor.
1686     *
1687     * @return returns this editor's standard action group
1688     */

1689    protected ActionGroup getActionGroup() {
1690        return fActionGroups;
1691    }
1692
1693    /*
1694     * @see AbstractTextEditor#editorContextMenuAboutToShow
1695     */

1696    public void editorContextMenuAboutToShow(IMenuManager menu) {
1697
1698        super.editorContextMenuAboutToShow(menu);
1699        menu.insertAfter(IContextMenuConstants.GROUP_OPEN, new GroupMarker(IContextMenuConstants.GROUP_SHOW));
1700
1701        ActionContext context= new ActionContext(getSelectionProvider().getSelection());
1702        fContextMenuGroup.setContext(context);
1703        fContextMenuGroup.fillContextMenu(menu);
1704        fContextMenuGroup.setContext(null);
1705
1706        // Quick views
1707
IAction action= getAction(IJavaEditorActionDefinitionIds.SHOW_OUTLINE);
1708        menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, action);
1709        action= getAction(IJavaEditorActionDefinitionIds.OPEN_HIERARCHY);
1710        menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, action);
1711        
1712    }
1713
1714    /**
1715     * Creates the outline page used with this editor.
1716     *
1717     * @return the created Java outline page
1718     */

1719    protected JavaOutlinePage createOutlinePage() {
1720        JavaOutlinePage page= new JavaOutlinePage(fOutlinerContextMenuId, this);
1721        fOutlineSelectionChangedListener.install(page);
1722        setOutlinePageInput(page, getEditorInput());
1723        return page;
1724    }
1725
1726    /**
1727     * Informs the editor that its outliner has been closed.
1728     */

1729    public void outlinePageClosed() {
1730        if (fOutlinePage != null) {
1731            fOutlineSelectionChangedListener.uninstall(fOutlinePage);
1732            fOutlinePage= null;
1733            resetHighlightRange();
1734        }
1735    }
1736
1737    /**
1738     * Synchronizes the outliner selection with the given element
1739     * position in the editor.
1740     *
1741     * @param element the java element to select
1742     */

1743    protected void synchronizeOutlinePage(ISourceReference element) {
1744        synchronizeOutlinePage(element, true);
1745    }
1746
1747    /**
1748     * Synchronizes the outliner selection with the given element
1749     * position in the editor.
1750     *
1751     * @param element the java element to select
1752     * @param checkIfOutlinePageActive <code>true</code> if check for active outline page needs to be done
1753     */

1754    protected void synchronizeOutlinePage(ISourceReference element, boolean checkIfOutlinePageActive) {
1755        if (fOutlinePage != null && element != null && !(checkIfOutlinePageActive && isJavaOutlinePageActive())) {
1756            fOutlineSelectionChangedListener.uninstall(fOutlinePage);
1757            fOutlinePage.select(element);
1758            fOutlineSelectionChangedListener.install(fOutlinePage);
1759        }
1760    }
1761
1762    /**
1763     * Synchronizes the outliner selection with the actual cursor
1764     * position in the editor.
1765     */

1766    public void synchronizeOutlinePageSelection() {
1767        synchronizeOutlinePage(computeHighlightRangeSourceReference());
1768    }
1769
1770    /*
1771     * @see AbstractTextEditor#getAdapter(Class)
1772     */

1773    public Object JavaDoc getAdapter(Class JavaDoc required) {
1774
1775        if (IContentOutlinePage.class.equals(required)) {
1776            if (fOutlinePage == null)
1777                fOutlinePage= createOutlinePage();
1778            return fOutlinePage;
1779        }
1780
1781        if (IEncodingSupport.class.equals(required))
1782            return fEncodingSupport;
1783
1784        if (required == IShowInTargetList.class) {
1785            return new IShowInTargetList() {
1786                public String JavaDoc[] getShowInTargetIds() {
1787                    return new String JavaDoc[] { JavaUI.ID_PACKAGES, IPageLayout.ID_OUTLINE, IPageLayout.ID_RES_NAV };
1788                }
1789
1790            };
1791        }
1792
1793        if (required == IShowInSource.class) {
1794            IJavaElement inputJE= getInputJavaElement();
1795            if (inputJE instanceof ICompilationUnit && !JavaModelUtil.isPrimary((ICompilationUnit) inputJE))
1796                return null;
1797            
1798            return new IShowInSource() {
1799                public ShowInContext getShowInContext() {
1800                    return new ShowInContext(getEditorInput(), null) {
1801                        /*
1802                         * @see org.eclipse.ui.part.ShowInContext#getSelection()
1803                         * @since 3.3
1804                         */

1805                        public ISelection getSelection() {
1806                            try {
1807                                IJavaElement je= SelectionConverter.getElementAtOffset(JavaEditor.this);
1808                                if (je != null)
1809                                    return new StructuredSelection(je);
1810                                return null;
1811                            } catch (JavaModelException ex) {
1812                                return null;
1813                            }
1814                        }
1815                    };
1816                }
1817            };
1818        }
1819
1820        if (required == IJavaFoldingStructureProvider.class)
1821            return fProjectionModelUpdater;
1822
1823        if (fProjectionSupport != null) {
1824            Object JavaDoc adapter= fProjectionSupport.getAdapter(getSourceViewer(), required);
1825            if (adapter != null)
1826                return adapter;
1827        }
1828
1829        if (required == IContextProvider.class)
1830            return JavaUIHelp.getHelpContextProvider(this, IJavaHelpContextIds.JAVA_EDITOR);
1831
1832        return super.getAdapter(required);
1833    }
1834
1835    /**
1836     * React to changed selection.
1837     *
1838     * @since 3.0
1839     */

1840    protected void selectionChanged() {
1841        if (getSelectionProvider() == null)
1842            return;
1843        ISourceReference element= computeHighlightRangeSourceReference();
1844        if (getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
1845            synchronizeOutlinePage(element);
1846        setSelection(element, false);
1847        if (!fSelectionChangedViaGotoAnnotation)
1848            updateStatusLine();
1849        fSelectionChangedViaGotoAnnotation= false;
1850    }
1851
1852    protected void setSelection(ISourceReference reference, boolean moveCursor) {
1853        if (getSelectionProvider() == null)
1854            return;
1855
1856        ISelection selection= getSelectionProvider().getSelection();
1857        if (selection instanceof ITextSelection) {
1858            ITextSelection textSelection= (ITextSelection) selection;
1859            // PR 39995: [navigation] Forward history cleared after going back in navigation history:
1860
// mark only in navigation history if the cursor is being moved (which it isn't if
1861
// this is called from a PostSelectionEvent that should only update the magnet)
1862
if (moveCursor && (textSelection.getOffset() != 0 || textSelection.getLength() != 0))
1863                markInNavigationHistory();
1864        }
1865
1866        if (reference != null) {
1867
1868            StyledText textWidget= null;
1869
1870            ISourceViewer sourceViewer= getSourceViewer();
1871            if (sourceViewer != null)
1872                textWidget= sourceViewer.getTextWidget();
1873
1874            if (textWidget == null)
1875                return;
1876
1877            try {
1878                ISourceRange range= null;
1879                if (reference instanceof ILocalVariable) {
1880                    IJavaElement je= ((ILocalVariable)reference).getParent();
1881                    if (je instanceof ISourceReference)
1882                        range= ((ISourceReference)je).getSourceRange();
1883                } else
1884                    range= reference.getSourceRange();
1885
1886                if (range == null)
1887                    return;
1888
1889                int offset= range.getOffset();
1890                int length= range.getLength();
1891
1892                if (offset < 0 || length < 0)
1893                    return;
1894
1895                setHighlightRange(offset, length, moveCursor);
1896
1897                if (!moveCursor)
1898                    return;
1899
1900                offset= -1;
1901                length= -1;
1902
1903                if (reference instanceof IMember) {
1904                    range= ((IMember) reference).getNameRange();
1905                    if (range != null) {
1906                        offset= range.getOffset();
1907                        length= range.getLength();
1908                    }
1909                } else if (reference instanceof ITypeParameter) {
1910                    range= ((ITypeParameter) reference).getNameRange();
1911                    if (range != null) {
1912                        offset= range.getOffset();
1913                        length= range.getLength();
1914                    }
1915                } else if (reference instanceof ILocalVariable) {
1916                    range= ((ILocalVariable)reference).getNameRange();
1917                    if (range != null) {
1918                        offset= range.getOffset();
1919                        length= range.getLength();
1920                    }
1921                } else if (reference instanceof IImportDeclaration) {
1922                    String JavaDoc content= reference.getSource();
1923                    if (content != null) {
1924                        int start= content.indexOf("import") + 6; //$NON-NLS-1$
1925
while (start < content.length() && content.charAt(start) == ' ')
1926                            start++;
1927                        
1928                        int end= content.indexOf(';');
1929                        do {
1930                            end--;
1931                        } while (end >= 0 && content.charAt(end) == ' ');
1932                        
1933                        offset= range.getOffset() + start;
1934                        length= end - start + 1;
1935                    } else {
1936                        // fallback
1937
offset= range.getOffset();
1938                        length= range.getLength();
1939                    }
1940                } else if (reference instanceof IPackageDeclaration) {
1941                    String JavaDoc name= ((IPackageDeclaration) reference).getElementName();
1942                    if (name != null && name.length() > 0) {
1943                        String JavaDoc content= reference.getSource();
1944                        if (content != null) {
1945                            int packageKeyWordIndex = content.lastIndexOf("package"); //$NON-NLS-1$
1946
if (packageKeyWordIndex != -1) {
1947                                offset= range.getOffset() + content.indexOf(name, packageKeyWordIndex + 7);
1948                                length= name.length();
1949                            }
1950                        }
1951                    }
1952                }
1953
1954                if (offset > -1 && length > 0) {
1955
1956                    try {
1957                        textWidget.setRedraw(false);
1958                        sourceViewer.revealRange(offset, length);
1959                        sourceViewer.setSelectedRange(offset, length);
1960                    } finally {
1961                        textWidget.setRedraw(true);
1962                    }
1963
1964                    markInNavigationHistory();
1965                }
1966
1967            } catch (JavaModelException x) {
1968            } catch (IllegalArgumentException JavaDoc x) {
1969            }
1970
1971        } else if (moveCursor) {
1972            resetHighlightRange();
1973            markInNavigationHistory();
1974        }
1975    }
1976
1977    public void setSelection(IJavaElement element) {
1978
1979        if (element == null || element instanceof ICompilationUnit || element instanceof IClassFile) {
1980            /*
1981             * If the element is an ICompilationUnit this unit is either the input
1982             * of this editor or not being displayed. In both cases, nothing should
1983             * happened. (http://dev.eclipse.org/bugs/show_bug.cgi?id=5128)
1984             */

1985            return;
1986        }
1987
1988        IJavaElement corresponding= getCorrespondingElement(element);
1989        if (corresponding instanceof ISourceReference) {
1990            ISourceReference reference= (ISourceReference) corresponding;
1991            // set highlight range
1992
setSelection(reference, true);
1993            // set outliner selection
1994
if (fOutlinePage != null) {
1995                fOutlineSelectionChangedListener.uninstall(fOutlinePage);
1996                fOutlinePage.select(reference);
1997                fOutlineSelectionChangedListener.install(fOutlinePage);
1998            }
1999        }
2000    }
2001
2002    protected void doSelectionChanged(SelectionChangedEvent event) {
2003
2004        ISourceReference reference= null;
2005
2006        ISelection selection= event.getSelection();
2007        Iterator iter= ((IStructuredSelection) selection).iterator();
2008        while (iter.hasNext()) {
2009            Object JavaDoc o= iter.next();
2010            if (o instanceof ISourceReference) {
2011                reference= (ISourceReference) o;
2012                break;
2013            }
2014        }
2015        if (!isActivePart() && JavaPlugin.getActivePage() != null)
2016            JavaPlugin.getActivePage().bringToTop(this);
2017
2018        setSelection(reference, !isActivePart());
2019        
2020        ISelectionProvider selectionProvider= getSelectionProvider();
2021        if (selectionProvider == null )
2022            return;
2023        
2024        ISelection textSelection= selectionProvider.getSelection();
2025        if (!(textSelection instanceof ITextSelection))
2026            return;
2027        
2028        CompilationUnit ast= JavaPlugin.getDefault().getASTProvider().getAST(getInputJavaElement(), ASTProvider.WAIT_ACTIVE_ONLY, getProgressMonitor());
2029        if (ast != null) {
2030            fForcedMarkOccurrencesSelection= textSelection;
2031            updateOccurrenceAnnotations((ITextSelection)textSelection, ast);
2032        }
2033        
2034    }
2035
2036    /*
2037     * @see AbstractTextEditor#adjustHighlightRange(int, int)
2038     */

2039    protected void adjustHighlightRange(int offset, int length) {
2040
2041        try {
2042
2043            IJavaElement element= getElementAt(offset, false);
2044            while (element instanceof ISourceReference) {
2045                ISourceRange range= ((ISourceReference) element).getSourceRange();
2046                if (range != null && offset < range.getOffset() + range.getLength() && range.getOffset() < offset + length) {
2047
2048                    ISourceViewer viewer= getSourceViewer();
2049                    if (viewer instanceof ITextViewerExtension5) {
2050                        ITextViewerExtension5 extension= (ITextViewerExtension5) viewer;
2051                        extension.exposeModelRange(new Region(range.getOffset(), range.getLength()));
2052                    }
2053
2054                    setHighlightRange(range.getOffset(), range.getLength(), true);
2055                    if (fOutlinePage != null) {
2056                        fOutlineSelectionChangedListener.uninstall(fOutlinePage);
2057                        fOutlinePage.select((ISourceReference) element);
2058                        fOutlineSelectionChangedListener.install(fOutlinePage);
2059                    }
2060
2061                    return;
2062                }
2063                element= element.getParent();
2064            }
2065
2066        } catch (JavaModelException x) {
2067            JavaPlugin.log(x.getStatus());
2068        }
2069
2070        ISourceViewer viewer= getSourceViewer();
2071        if (viewer instanceof ITextViewerExtension5) {
2072            ITextViewerExtension5 extension= (ITextViewerExtension5) viewer;
2073            extension.exposeModelRange(new Region(offset, length));
2074        } else {
2075            resetHighlightRange();
2076        }
2077
2078    }
2079
2080    protected boolean isActivePart() {
2081        IWorkbenchPart part= getActivePart();
2082        return part != null && part.equals(this);
2083    }
2084
2085    private boolean isJavaOutlinePageActive() {
2086        IWorkbenchPart part= getActivePart();
2087        return part instanceof ContentOutline && ((ContentOutline)part).getCurrentPage() == fOutlinePage;
2088    }
2089
2090    private IWorkbenchPart getActivePart() {
2091        IWorkbenchWindow window= getSite().getWorkbenchWindow();
2092        IPartService service= window.getPartService();
2093        IWorkbenchPart part= service.getActivePart();
2094        return part;
2095    }
2096
2097    /*
2098     * @see StatusTextEditor#getStatusHeader(IStatus)
2099     */

2100    protected String JavaDoc getStatusHeader(IStatus status) {
2101        if (fEncodingSupport != null) {
2102            String JavaDoc message= fEncodingSupport.getStatusHeader(status);
2103            if (message != null)
2104                return message;
2105        }
2106        return super.getStatusHeader(status);
2107    }
2108
2109    /*
2110     * @see StatusTextEditor#getStatusBanner(IStatus)
2111     */

2112    protected String JavaDoc getStatusBanner(IStatus status) {
2113        if (fEncodingSupport != null) {
2114            String JavaDoc message= fEncodingSupport.getStatusBanner(status);
2115            if (message != null)
2116                return message;
2117        }
2118        return super.getStatusBanner(status);
2119    }
2120
2121    /*
2122     * @see StatusTextEditor#getStatusMessage(IStatus)
2123     */

2124    protected String JavaDoc getStatusMessage(IStatus status) {
2125        if (fEncodingSupport != null) {
2126            String JavaDoc message= fEncodingSupport.getStatusMessage(status);
2127            if (message != null)
2128                return message;
2129        }
2130        return super.getStatusMessage(status);
2131    }
2132
2133    /*
2134     * @see AbstractTextEditor#doSetInput
2135     */

2136    protected void doSetInput(IEditorInput input) throws CoreException {
2137        ISourceViewer sourceViewer= getSourceViewer();
2138        if (!(sourceViewer instanceof ISourceViewerExtension2)) {
2139            setPreferenceStore(createCombinedPreferenceStore(input));
2140            internalDoSetInput(input);
2141            return;
2142        }
2143
2144        // uninstall & unregister preference store listener
2145
getSourceViewerDecorationSupport(sourceViewer).uninstall();
2146        ((ISourceViewerExtension2)sourceViewer).unconfigure();
2147
2148        setPreferenceStore(createCombinedPreferenceStore(input));
2149
2150        // install & register preference store listener
2151
sourceViewer.configure(getSourceViewerConfiguration());
2152        getSourceViewerDecorationSupport(sourceViewer).install(getPreferenceStore());
2153
2154        internalDoSetInput(input);
2155    }
2156
2157    private void internalDoSetInput(IEditorInput input) throws CoreException {
2158        ISourceViewer sourceViewer= getSourceViewer();
2159        JavaSourceViewer javaSourceViewer= null;
2160        if (sourceViewer instanceof JavaSourceViewer)
2161            javaSourceViewer= (JavaSourceViewer)sourceViewer;
2162        
2163        IPreferenceStore store= getPreferenceStore();
2164        if (javaSourceViewer != null && isFoldingEnabled() &&(store == null || !store.getBoolean(PreferenceConstants.EDITOR_SHOW_SEGMENTS)))
2165            javaSourceViewer.prepareDelayedProjection();
2166        
2167        super.doSetInput(input);
2168
2169        if (javaSourceViewer != null && javaSourceViewer.getReconciler() == null) {
2170            IReconciler reconciler= getSourceViewerConfiguration().getReconciler(javaSourceViewer);
2171            if (reconciler != null) {
2172                reconciler.install(javaSourceViewer);
2173                javaSourceViewer.setReconciler(reconciler);
2174            }
2175        }
2176
2177        if (fEncodingSupport != null)
2178            fEncodingSupport.reset();
2179
2180        setOutlinePageInput(fOutlinePage, input);
2181
2182        if (isShowingOverrideIndicators())
2183            installOverrideIndicator(false);
2184    }
2185
2186    /*
2187     * @see org.eclipse.ui.texteditor.AbstractTextEditor#setPreferenceStore(org.eclipse.jface.preference.IPreferenceStore)
2188     * @since 3.0
2189     */

2190    protected void setPreferenceStore(IPreferenceStore store) {
2191        super.setPreferenceStore(store);
2192        if (getSourceViewerConfiguration() instanceof JavaSourceViewerConfiguration) {
2193            JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools();
2194            setSourceViewerConfiguration(new JavaSourceViewerConfiguration(textTools.getColorManager(), store, this, IJavaPartitions.JAVA_PARTITIONING));
2195        }
2196        if (getSourceViewer() instanceof JavaSourceViewer)
2197            ((JavaSourceViewer)getSourceViewer()).setPreferenceStore(store);
2198    }
2199
2200    /*
2201     * @see IWorkbenchPart#dispose()
2202     */

2203    public void dispose() {
2204
2205        if (fProjectionModelUpdater != null) {
2206            fProjectionModelUpdater.uninstall();
2207            fProjectionModelUpdater= null;
2208        }
2209
2210        if (fProjectionSupport != null) {
2211            fProjectionSupport.dispose();
2212            fProjectionSupport= null;
2213        }
2214
2215        // cancel possible running computation
2216
fMarkOccurrenceAnnotations= false;
2217        uninstallOccurrencesFinder();
2218
2219        uninstallOverrideIndicator();
2220
2221        uninstallSemanticHighlighting();
2222
2223        if (fActivationListener != null) {
2224            PlatformUI.getWorkbench().removeWindowListener(fActivationListener);
2225            fActivationListener= null;
2226        }
2227
2228        if (fEncodingSupport != null) {
2229            fEncodingSupport.dispose();
2230            fEncodingSupport= null;
2231        }
2232
2233        if (fBracketMatcher != null) {
2234            fBracketMatcher.dispose();
2235            fBracketMatcher= null;
2236        }
2237
2238        if (fSelectionHistory != null) {
2239            fSelectionHistory.dispose();
2240            fSelectionHistory= null;
2241        }
2242
2243        if (fEditorSelectionChangedListener != null) {
2244            fEditorSelectionChangedListener.uninstall(getSelectionProvider());
2245            fEditorSelectionChangedListener= null;
2246        }
2247
2248        if (fActionGroups != null) {
2249            fActionGroups.dispose();
2250            fActionGroups= null;
2251        }
2252        
2253        super.dispose();
2254    }
2255
2256    protected void createActions() {
2257        installEncodingSupport();
2258        
2259        super.createActions();
2260
2261        ActionGroup oeg, ovg, jsg;
2262        fActionGroups= new CompositeActionGroup(new ActionGroup[] {
2263            oeg= new OpenEditorActionGroup(this),
2264            ovg= new OpenViewActionGroup(this),
2265            jsg= new JavaSearchActionGroup(this)
2266        });
2267        fContextMenuGroup= new CompositeActionGroup(new ActionGroup[] {oeg, ovg, jsg});
2268
2269        fFoldingGroup= new FoldingActionGroup(this, getViewer());
2270
2271        Action action= new GotoMatchingBracketAction(this);
2272        action.setActionDefinitionId(IJavaEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);
2273        setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action);
2274
2275        action= new TextOperationAction(JavaEditorMessages.getBundleForConstructedKeys(),"ShowOutline.", this, JavaSourceViewer.SHOW_OUTLINE, true); //$NON-NLS-1$
2276
action.setActionDefinitionId(IJavaEditorActionDefinitionIds.SHOW_OUTLINE);
2277        setAction(IJavaEditorActionDefinitionIds.SHOW_OUTLINE, action);
2278        PlatformUI.getWorkbench().getHelpSystem().setHelp(action, IJavaHelpContextIds.SHOW_OUTLINE_ACTION);
2279
2280        action= new TextOperationAction(JavaEditorMessages.getBundleForConstructedKeys(),"OpenStructure.", this, JavaSourceViewer.OPEN_STRUCTURE, true); //$NON-NLS-1$
2281
action.setActionDefinitionId(IJavaEditorActionDefinitionIds.OPEN_STRUCTURE);
2282        setAction(IJavaEditorActionDefinitionIds.OPEN_STRUCTURE, action);
2283        PlatformUI.getWorkbench().getHelpSystem().setHelp(action, IJavaHelpContextIds.OPEN_STRUCTURE_ACTION);
2284
2285        action= new TextOperationAction(JavaEditorMessages.getBundleForConstructedKeys(),"OpenHierarchy.", this, JavaSourceViewer.SHOW_HIERARCHY, true); //$NON-NLS-1$
2286
action.setActionDefinitionId(IJavaEditorActionDefinitionIds.OPEN_HIERARCHY);
2287        setAction(IJavaEditorActionDefinitionIds.OPEN_HIERARCHY, action);
2288        PlatformUI.getWorkbench().getHelpSystem().setHelp(action, IJavaHelpContextIds.OPEN_HIERARCHY_ACTION);
2289
2290        fSelectionHistory= new SelectionHistory(this);
2291
2292        action= new StructureSelectEnclosingAction(this, fSelectionHistory);
2293        action.setActionDefinitionId(IJavaEditorActionDefinitionIds.SELECT_ENCLOSING);
2294        setAction(StructureSelectionAction.ENCLOSING, action);
2295
2296        action= new StructureSelectNextAction(this, fSelectionHistory);
2297        action.setActionDefinitionId(IJavaEditorActionDefinitionIds.SELECT_NEXT);
2298        setAction(StructureSelectionAction.NEXT, action);
2299
2300        action= new StructureSelectPreviousAction(this, fSelectionHistory);
2301        action.setActionDefinitionId(IJavaEditorActionDefinitionIds.SELECT_PREVIOUS);
2302        setAction(StructureSelectionAction.PREVIOUS, action);
2303
2304        StructureSelectHistoryAction historyAction= new StructureSelectHistoryAction(this, fSelectionHistory);
2305        historyAction.setActionDefinitionId(IJavaEditorActionDefinitionIds.SELECT_LAST);
2306        setAction(StructureSelectionAction.HISTORY, historyAction);
2307        fSelectionHistory.setHistoryAction(historyAction);
2308
2309        action= GoToNextPreviousMemberAction.newGoToNextMemberAction(this);
2310        action.setActionDefinitionId(IJavaEditorActionDefinitionIds.GOTO_NEXT_MEMBER);
2311        setAction(GoToNextPreviousMemberAction.NEXT_MEMBER, action);
2312
2313        action= GoToNextPreviousMemberAction.newGoToPreviousMemberAction(this);
2314        action.setActionDefinitionId(IJavaEditorActionDefinitionIds.GOTO_PREVIOUS_MEMBER);
2315        setAction(GoToNextPreviousMemberAction.PREVIOUS_MEMBER, action);
2316
2317        action= new FormatElementAction();
2318        action.setActionDefinitionId(IJavaEditorActionDefinitionIds.QUICK_FORMAT);
2319        setAction("QuickFormat", action); //$NON-NLS-1$
2320
markAsStateDependentAction("QuickFormat", true); //$NON-NLS-1$
2321

2322        action= new RemoveOccurrenceAnnotations(this);
2323        action.setActionDefinitionId(IJavaEditorActionDefinitionIds.REMOVE_OCCURRENCE_ANNOTATIONS);
2324        setAction("RemoveOccurrenceAnnotations", action); //$NON-NLS-1$
2325

2326        // add annotation actions for roll-over expand hover
2327
action= new JavaSelectMarkerRulerAction2(JavaEditorMessages.getBundleForConstructedKeys(), "Editor.RulerAnnotationSelection.", this); //$NON-NLS-1$
2328
setAction("AnnotationAction", action); //$NON-NLS-1$
2329

2330        action= new ShowInPackageViewAction(this);
2331        action.setActionDefinitionId(IJavaEditorActionDefinitionIds.SHOW_IN_PACKAGE_VIEW);
2332        setAction("ShowInPackageView", action); //$NON-NLS-1$
2333

2334
2335        // replace cut/copy paste actions with a version that implement 'add imports on paste'
2336

2337        action= new ClipboardOperationAction(JavaEditorMessages.getBundleForConstructedKeys(), "Editor.Cut.", this, ITextOperationTarget.CUT); //$NON-NLS-1$
2338
setAction(ITextEditorActionConstants.CUT, action);
2339
2340        action= new ClipboardOperationAction(JavaEditorMessages.getBundleForConstructedKeys(), "Editor.Copy.", this, ITextOperationTarget.COPY); //$NON-NLS-1$
2341
setAction(ITextEditorActionConstants.COPY, action);
2342
2343        action= new ClipboardOperationAction(JavaEditorMessages.getBundleForConstructedKeys(), "Editor.Paste.", this, ITextOperationTarget.PASTE); //$NON-NLS-1$
2344
setAction(ITextEditorActionConstants.PASTE, action);
2345        
2346        action= new CopyQualifiedNameAction(this);
2347        setAction(IJavaEditorActionConstants.COPY_QUALIFIED_NAME, action);
2348    }
2349    
2350    /**
2351     * Installs the encoding support on the given text editor.
2352     * <p>
2353     * Subclasses may override to install their own encoding
2354     * support or to disable the default encoding support.
2355     * </p>
2356     * @since 3.2
2357     */

2358    protected void installEncodingSupport() {
2359        fEncodingSupport= new DefaultEncodingSupport();
2360        fEncodingSupport.initialize(this);
2361    }
2362    
2363
2364    public void updatedTitleImage(Image image) {
2365        setTitleImage(image);
2366    }
2367
2368    /*
2369     * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
2370     */

2371    protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
2372
2373        String JavaDoc property= event.getProperty();
2374
2375        if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) {
2376            /*
2377             * Ignore tab setting since we rely on the formatter preferences.
2378             * We do this outside the try-finally block to avoid that EDITOR_TAB_WIDTH
2379             * is handled by the sub-class (AbstractDecoratedTextEditor).
2380             */

2381            return;
2382        }
2383
2384        try {
2385
2386            ISourceViewer sourceViewer= getSourceViewer();
2387            if (sourceViewer == null)
2388                return;
2389
2390            if (isJavaEditorHoverProperty(property))
2391                updateHoverBehavior();
2392
2393            boolean newBooleanValue= false;
2394            Object JavaDoc newValue= event.getNewValue();
2395            if (newValue != null)
2396                newBooleanValue= Boolean.valueOf(newValue.toString()).booleanValue();
2397
2398            if (PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE.equals(property)) {
2399                if (newBooleanValue)
2400                    selectionChanged();
2401                return;
2402            }
2403
2404            if (PreferenceConstants.EDITOR_MARK_OCCURRENCES.equals(property)) {
2405                if (newBooleanValue != fMarkOccurrenceAnnotations) {
2406                    fMarkOccurrenceAnnotations= newBooleanValue;
2407                    if (!fMarkOccurrenceAnnotations)
2408                        uninstallOccurrencesFinder();
2409                    else
2410                        installOccurrencesFinder(true);
2411                }
2412                return;
2413            }
2414            if (PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES.equals(property)) {
2415                fMarkTypeOccurrences= newBooleanValue;
2416                return;
2417            }
2418            if (PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES.equals(property)) {
2419                fMarkMethodOccurrences= newBooleanValue;
2420                return;
2421            }
2422            if (PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES.equals(property)) {
2423                fMarkConstantOccurrences= newBooleanValue;
2424                return;
2425            }
2426            if (PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES.equals(property)) {
2427                fMarkFieldOccurrences= newBooleanValue;
2428                return;
2429            }
2430            if (PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES.equals(property)) {
2431                fMarkLocalVariableypeOccurrences= newBooleanValue;
2432                return;
2433            }
2434            if (PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES.equals(property)) {
2435                fMarkExceptions= newBooleanValue;
2436                return;
2437            }
2438            if (PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS.equals(property)) {
2439                fMarkMethodExitPoints= newBooleanValue;
2440                return;
2441            }
2442            if (PreferenceConstants.EDITOR_MARK_BREAK_CONTINUE_TARGETS.equals(property)) {
2443                fMarkBreakContinueTargets= newBooleanValue;
2444                return;
2445            }
2446            if (PreferenceConstants.EDITOR_MARK_IMPLEMENTORS.equals(property)) {
2447                fMarkImplementors= newBooleanValue;
2448                return;
2449            }
2450            if (PreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property)) {
2451                fStickyOccurrenceAnnotations= newBooleanValue;
2452                return;
2453            }
2454            if (SemanticHighlightings.affectsEnablement(getPreferenceStore(), event)) {
2455                if (isSemanticHighlightingEnabled())
2456                    installSemanticHighlighting();
2457                else
2458                    uninstallSemanticHighlighting();
2459                return;
2460            }
2461
2462            if (JavaCore.COMPILER_SOURCE.equals(property)) {
2463                if (event.getNewValue() instanceof String JavaDoc)
2464                    fBracketMatcher.setSourceVersion((String JavaDoc) event.getNewValue());
2465                // fall through as others are interested in source change as well.
2466
}
2467
2468            ((JavaSourceViewerConfiguration)getSourceViewerConfiguration()).handlePropertyChangeEvent(event);
2469
2470            if (affectsOverrideIndicatorAnnotations(event)) {
2471                if (isShowingOverrideIndicators()) {
2472                    if (fOverrideIndicatorManager == null)
2473                        installOverrideIndicator(true);
2474                } else {
2475                    if (fOverrideIndicatorManager != null)
2476                        uninstallOverrideIndicator();
2477                }
2478                return;
2479            }
2480
2481            if (PreferenceConstants.EDITOR_FOLDING_PROVIDER.equals(property)) {
2482                if (sourceViewer instanceof ProjectionViewer) {
2483                    ProjectionViewer projectionViewer= (ProjectionViewer) sourceViewer;
2484                    if (fProjectionModelUpdater != null)
2485                        fProjectionModelUpdater.uninstall();
2486                    // either freshly enabled or provider changed
2487
fProjectionModelUpdater= JavaPlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider();
2488                    if (fProjectionModelUpdater != null) {
2489                        fProjectionModelUpdater.install(this, projectionViewer);
2490                    }
2491                }
2492                return;
2493            }
2494
2495            if (DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE.equals(property)
2496                    || DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE.equals(property)
2497                    || DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR.equals(property)) {
2498                StyledText textWidget= sourceViewer.getTextWidget();
2499                int tabWidth= getSourceViewerConfiguration().getTabWidth(sourceViewer);
2500                if (textWidget.getTabs() != tabWidth)
2501                    textWidget.setTabs(tabWidth);
2502                return;
2503            }
2504
2505            if (PreferenceConstants.EDITOR_FOLDING_ENABLED.equals(property)) {
2506                if (sourceViewer instanceof ProjectionViewer) {
2507                    new ToggleFoldingRunner().runWhenNextVisible();
2508                }
2509                return;
2510            }
2511
2512        } finally {
2513            super.handlePreferenceStoreChanged(event);
2514        }
2515        
2516        if (AbstractDecoratedTextEditorPreferenceConstants.SHOW_RANGE_INDICATOR.equals(property)) {
2517            // superclass already installed the range indicator
2518
Object JavaDoc newValue= event.getNewValue();
2519            ISourceViewer viewer= getSourceViewer();
2520            if (newValue != null && viewer != null) {
2521                if (Boolean.valueOf(newValue.toString()).booleanValue()) {
2522                    // adjust the highlightrange in order to get the magnet right after changing the selection
2523
Point selection= viewer.getSelectedRange();
2524                    adjustHighlightRange(selection.x, selection.y);
2525                }
2526            }
2527
2528        }
2529    }
2530
2531    /**
2532     * Initializes the given viewer's colors.
2533     *
2534     * @param viewer the viewer to be initialized
2535     * @since 3.0
2536     */

2537    protected void initializeViewerColors(ISourceViewer viewer) {
2538        // is handled by JavaSourceViewer
2539
}
2540
2541    private boolean isJavaEditorHoverProperty(String JavaDoc property) {
2542        return PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS.equals(property);
2543    }
2544
2545    /*
2546     * @see org.eclipse.ui.texteditor.AbstractTextEditor#updatePropertyDependentActions()
2547     */

2548    protected void updatePropertyDependentActions() {
2549        super.updatePropertyDependentActions();
2550        if (fEncodingSupport != null)
2551            fEncodingSupport.reset();
2552    }
2553
2554    /*
2555     * Update the hovering behavior depending on the preferences.
2556     */

2557    private void updateHoverBehavior() {
2558        SourceViewerConfiguration configuration= getSourceViewerConfiguration();
2559        String JavaDoc[] types= configuration.getConfiguredContentTypes(getSourceViewer());
2560
2561        for (int i= 0; i < types.length; i++) {
2562
2563            String JavaDoc t= types[i];
2564
2565            ISourceViewer sourceViewer= getSourceViewer();
2566            if (sourceViewer instanceof ITextViewerExtension2) {
2567                // Remove existing hovers
2568
((ITextViewerExtension2)sourceViewer).removeTextHovers(t);
2569
2570                int[] stateMasks= configuration.getConfiguredTextHoverStateMasks(getSourceViewer(), t);
2571
2572                if (stateMasks != null) {
2573                    for (int j= 0; j < stateMasks.length; j++) {
2574                        int stateMask= stateMasks[j];
2575                        ITextHover textHover= configuration.getTextHover(sourceViewer, t, stateMask);
2576                        ((ITextViewerExtension2)sourceViewer).setTextHover(textHover, t, stateMask);
2577                    }
2578                } else {
2579                    ITextHover textHover= configuration.getTextHover(sourceViewer, t);
2580                    ((ITextViewerExtension2)sourceViewer).setTextHover(textHover, t, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
2581                }
2582            } else
2583                sourceViewer.setTextHover(configuration.getTextHover(sourceViewer, t), t);
2584        }
2585    }
2586
2587    /*
2588     * @see org.eclipse.jdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
2589     */

2590    public Object JavaDoc getViewPartInput() {
2591        return getEditorInput().getAdapter(IJavaElement.class);
2592    }
2593
2594    /*
2595     * @see org.eclipse.ui.texteditor.AbstractTextEditor#doSetSelection(ISelection)
2596     */

2597    protected void doSetSelection(ISelection selection) {
2598        super.doSetSelection(selection);
2599        synchronizeOutlinePageSelection();
2600    }
2601
2602    boolean isFoldingEnabled() {
2603        return JavaPlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_FOLDING_ENABLED);
2604    }
2605
2606    /*
2607     * @see org.eclipse.ui.part.WorkbenchPart#getOrientation()
2608     * @since 3.1
2609     */

2610    public int getOrientation() {
2611        return SWT.LEFT_TO_RIGHT; //Java editors are always left to right by default
2612
}
2613
2614    /*
2615     * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
2616     */

2617    public void createPartControl(Composite parent) {
2618        super.createPartControl(parent);
2619
2620        fEditorSelectionChangedListener= new EditorSelectionChangedListener();
2621        fEditorSelectionChangedListener.install(getSelectionProvider());
2622
2623        if (isSemanticHighlightingEnabled())
2624            installSemanticHighlighting();
2625
2626        PlatformUI.getWorkbench().addWindowListener(fActivationListener);
2627    }
2628
2629    protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) {
2630
2631        fBracketMatcher.setSourceVersion(getPreferenceStore().getString(JavaCore.COMPILER_SOURCE));
2632        support.setCharacterPairMatcher(fBracketMatcher);
2633        support.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR);
2634
2635        super.configureSourceViewerDecorationSupport(support);
2636    }
2637
2638    /**
2639     * Returns the lock object for the given annotation model.
2640     *
2641     * @param annotationModel the annotation model
2642     * @return the annotation model's lock object
2643     * @since 3.0
2644     */

2645    private Object JavaDoc getLockObject(IAnnotationModel annotationModel) {
2646        if (annotationModel instanceof ISynchronizable) {
2647            Object JavaDoc lock= ((ISynchronizable)annotationModel).getLockObject();
2648            if (lock != null)
2649                return lock;
2650        }
2651        return annotationModel;
2652    }
2653
2654    /*
2655     * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#updateMarkerViews(org.eclipse.jface.text.source.Annotation)
2656     * @since 3.2
2657     */

2658    protected void updateMarkerViews(Annotation annotation) {
2659        if (annotation instanceof IJavaAnnotation) {
2660            Iterator e= ((IJavaAnnotation) annotation).getOverlaidIterator();
2661            if (e != null) {
2662                while (e.hasNext()) {
2663                    Object JavaDoc o= e.next();
2664                    if (o instanceof MarkerAnnotation) {
2665                        super.updateMarkerViews((MarkerAnnotation)o);
2666                        return;
2667                    }
2668                }
2669            }
2670            return;
2671        }
2672        super.updateMarkerViews(annotation);
2673    }
2674
2675    /**
2676     * Finds and marks occurrence annotations.
2677     *
2678     * @since 3.0
2679     */

2680    class OccurrencesFinderJob extends Job {
2681
2682        private IDocument fDocument;
2683        private ISelection fSelection;
2684        private ISelectionValidator fPostSelectionValidator;
2685        private boolean fCanceled= false;
2686        private IProgressMonitor fProgressMonitor;
2687        private Position[] fPositions;
2688
2689        public OccurrencesFinderJob(IDocument document, Position[] positions, ISelection selection) {
2690            super(JavaEditorMessages.JavaEditor_markOccurrences_job_name);
2691            fDocument= document;
2692            fSelection= selection;
2693            fPositions= positions;
2694
2695            if (getSelectionProvider() instanceof ISelectionValidator)
2696                fPostSelectionValidator= (ISelectionValidator)getSelectionProvider();
2697        }
2698
2699        // cannot use cancel() because it is declared final
2700
void doCancel() {
2701            fCanceled= true;
2702            cancel();
2703        }
2704
2705        private boolean isCanceled() {
2706            return fCanceled || fProgressMonitor.isCanceled()
2707                || fPostSelectionValidator != null && !(fPostSelectionValidator.isValid(fSelection) || fForcedMarkOccurrencesSelection == fSelection)
2708                || LinkedModeModel.hasInstalledModel(fDocument);
2709        }
2710
2711        /*
2712         * @see Job#run(org.eclipse.core.runtime.IProgressMonitor)
2713         */

2714        public IStatus run(IProgressMonitor progressMonitor) {
2715
2716            fProgressMonitor= progressMonitor;
2717
2718            if (isCanceled())
2719                return Status.CANCEL_STATUS;
2720
2721            ITextViewer textViewer= getViewer();
2722            if (textViewer == null)
2723                return Status.CANCEL_STATUS;
2724
2725            IDocument document= textViewer.getDocument();
2726            if (document == null)
2727                return Status.CANCEL_STATUS;
2728
2729            IDocumentProvider documentProvider= getDocumentProvider();
2730            if (documentProvider == null)
2731                return Status.CANCEL_STATUS;
2732
2733            IAnnotationModel annotationModel= documentProvider.getAnnotationModel(getEditorInput());
2734            if (annotationModel == null)
2735                return Status.CANCEL_STATUS;
2736
2737            // Add occurrence annotations
2738
int length= fPositions.length;
2739            Map JavaDoc annotationMap= new HashMap JavaDoc(length);
2740            for (int i= 0; i < length; i++) {
2741
2742                if (isCanceled())
2743                    return Status.CANCEL_STATUS;
2744
2745                String JavaDoc message;
2746                Position position= fPositions[i];
2747
2748                // Create & add annotation
2749
try {
2750                    message= document.get(position.offset, position.length);
2751                } catch (BadLocationException ex) {
2752                    // Skip this match
2753
continue;
2754                }
2755                annotationMap.put(
2756                        new Annotation("org.eclipse.jdt.ui.occurrences", false, message), //$NON-NLS-1$
2757
position);
2758            }
2759
2760            if (isCanceled())
2761                return Status.CANCEL_STATUS;
2762
2763            synchronized (getLockObject(annotationModel)) {
2764                if (annotationModel instanceof IAnnotationModelExtension) {
2765                    ((IAnnotationModelExtension)annotationModel).replaceAnnotations(fOccurrenceAnnotations, annotationMap);
2766                } else {
2767                    removeOccurrenceAnnotations();
2768                    Iterator iter= annotationMap.entrySet().iterator();
2769                    while (iter.hasNext()) {
2770                        Map.Entry JavaDoc mapEntry= (Map.Entry JavaDoc)iter.next();
2771                        annotationModel.addAnnotation((Annotation)mapEntry.getKey(), (Position)mapEntry.getValue());
2772                    }
2773                }
2774                fOccurrenceAnnotations= (Annotation[])annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]);
2775            }
2776
2777            return Status.OK_STATUS;
2778        }
2779    }
2780
2781    /**
2782     * Updates the occurrences annotations based
2783     * on the current selection.
2784     *
2785     * @param selection the text selection
2786     * @param astRoot the compilation unit AST
2787     * @since 3.0
2788     */

2789    protected void updateOccurrenceAnnotations(ITextSelection selection, CompilationUnit astRoot) {
2790
2791        if (fOccurrencesFinderJob != null)
2792            fOccurrencesFinderJob.cancel();
2793
2794        if (!fMarkOccurrenceAnnotations)
2795            return;
2796
2797        if (astRoot == null || selection == null)
2798            return;
2799
2800        IDocument document= getSourceViewer().getDocument();
2801        if (document == null)
2802            return;
2803
2804        if (document instanceof IDocumentExtension4) {
2805            int offset= selection.getOffset();
2806            long currentModificationStamp= ((IDocumentExtension4)document).getModificationStamp();
2807            IRegion markOccurrenceTargetRegion= fMarkOccurrenceTargetRegion;
2808            if (markOccurrenceTargetRegion != null && currentModificationStamp == fMarkOccurrenceModificationStamp) {
2809                if (markOccurrenceTargetRegion.getOffset() <= offset && offset <= markOccurrenceTargetRegion.getOffset() + markOccurrenceTargetRegion.getLength())
2810                    return;
2811            }
2812            fMarkOccurrenceTargetRegion= JavaWordFinder.findWord(document, offset);
2813            fMarkOccurrenceModificationStamp= currentModificationStamp;
2814        }
2815
2816        List JavaDoc matches= null;
2817        
2818        ASTNode selectedNode= NodeFinder.perform(astRoot, selection.getOffset(), selection.getLength());
2819        
2820        if (fMarkExceptions || fMarkTypeOccurrences) {
2821            ExceptionOccurrencesFinder exceptionFinder= new ExceptionOccurrencesFinder();
2822            String JavaDoc message= exceptionFinder.initialize(astRoot, selectedNode);
2823            if (message == null) {
2824                matches= exceptionFinder.perform();
2825                if (!fMarkExceptions && !matches.isEmpty())
2826                    matches.clear();
2827            }
2828        }
2829
2830        if ((matches == null || matches.isEmpty()) && (fMarkMethodExitPoints || fMarkTypeOccurrences)) {
2831            MethodExitsFinder finder= new MethodExitsFinder();
2832            String JavaDoc message= finder.initialize(astRoot, selectedNode);
2833            if (message == null) {
2834                matches= finder.perform();
2835                if (!fMarkMethodExitPoints && !matches.isEmpty())
2836                    matches.clear();
2837            }
2838        }
2839
2840        if ((matches == null || matches.isEmpty()) && (fMarkBreakContinueTargets || fMarkTypeOccurrences)) {
2841            BreakContinueTargetFinder finder= new BreakContinueTargetFinder();
2842            String JavaDoc message= finder.initialize(astRoot, selectedNode);
2843            if (message == null) {
2844                matches= finder.perform();
2845                if (!fMarkBreakContinueTargets && !matches.isEmpty())
2846                    matches.clear();
2847            }
2848        }
2849
2850        if ((matches == null || matches.isEmpty()) && (fMarkImplementors || fMarkTypeOccurrences)) {
2851            ImplementOccurrencesFinder finder= new ImplementOccurrencesFinder();
2852            String JavaDoc message= finder.initialize(astRoot, selectedNode);
2853            if (message == null) {
2854                matches= finder.perform();
2855                if (!fMarkImplementors && !matches.isEmpty())
2856                    matches.clear();
2857            }
2858        }
2859
2860        if (matches == null) {
2861            IBinding binding= null;
2862            if (selectedNode instanceof Name)
2863                binding= ((Name)selectedNode).resolveBinding();
2864
2865            if (binding != null && markOccurrencesOfType(binding)) {
2866                // Find the matches && extract positions so we can forget the AST
2867
OccurrencesFinder finder = new OccurrencesFinder(binding);
2868                String JavaDoc message= finder.initialize(astRoot, selectedNode);
2869                if (message == null)
2870                    matches= finder.perform();
2871            }
2872        }
2873
2874        if (matches == null || matches.size() == 0) {
2875            if (!fStickyOccurrenceAnnotations)
2876                removeOccurrenceAnnotations();
2877            return;
2878        }
2879
2880        Position[] positions= new Position[matches.size()];
2881        int i= 0;
2882        for (Iterator each= matches.iterator(); each.hasNext();) {
2883            ASTNode currentNode= (ASTNode)each.next();
2884            positions[i++]= new Position(currentNode.getStartPosition(), currentNode.getLength());
2885        }
2886
2887        fOccurrencesFinderJob= new OccurrencesFinderJob(document, positions, selection);
2888        //fOccurrencesFinderJob.setPriority(Job.DECORATE);
2889
//fOccurrencesFinderJob.setSystem(true);
2890
//fOccurrencesFinderJob.schedule();
2891
fOccurrencesFinderJob.run(new NullProgressMonitor());
2892    }
2893
2894    protected void installOccurrencesFinder(boolean forceUpdate) {
2895        fMarkOccurrenceAnnotations= true;
2896
2897        fPostSelectionListenerWithAST= new ISelectionListenerWithAST() {
2898            public void selectionChanged(IEditorPart part, ITextSelection selection, CompilationUnit astRoot) {
2899                updateOccurrenceAnnotations(selection, astRoot);
2900            }
2901        };
2902        SelectionListenerWithASTManager.getDefault().addListener(this, fPostSelectionListenerWithAST);
2903        if (forceUpdate && getSelectionProvider() != null) {
2904            fForcedMarkOccurrencesSelection= getSelectionProvider().getSelection();
2905            updateOccurrenceAnnotations((ITextSelection)fForcedMarkOccurrencesSelection, JavaPlugin.getDefault().getASTProvider().getAST(getInputJavaElement(), ASTProvider.WAIT_NO, getProgressMonitor()));
2906        }
2907
2908        if (fOccurrencesFinderJobCanceler == null) {
2909            fOccurrencesFinderJobCanceler= new OccurrencesFinderJobCanceler();
2910            fOccurrencesFinderJobCanceler.install();
2911        }
2912    }
2913
2914    protected void uninstallOccurrencesFinder() {
2915        fMarkOccurrenceAnnotations= false;
2916
2917        if (fOccurrencesFinderJob != null) {
2918            fOccurrencesFinderJob.cancel();
2919            fOccurrencesFinderJob= null;
2920        }
2921
2922        if (fOccurrencesFinderJobCanceler != null) {
2923            fOccurrencesFinderJobCanceler.uninstall();
2924            fOccurrencesFinderJobCanceler= null;
2925        }
2926
2927        if (fPostSelectionListenerWithAST != null) {
2928            SelectionListenerWithASTManager.getDefault().removeListener(this, fPostSelectionListenerWithAST);
2929            fPostSelectionListenerWithAST= null;
2930        }
2931
2932        removeOccurrenceAnnotations();
2933    }
2934
2935    protected boolean isMarkingOccurrences() {
2936        IPreferenceStore store= getPreferenceStore();
2937        return store != null && store.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES);
2938    }
2939
2940    boolean markOccurrencesOfType(IBinding binding) {
2941
2942        if (binding == null)
2943            return false;
2944
2945        int kind= binding.getKind();
2946
2947        if (fMarkTypeOccurrences && kind == IBinding.TYPE)
2948            return true;
2949
2950        if (fMarkMethodOccurrences && kind == IBinding.METHOD)
2951            return true;
2952
2953        if (kind == IBinding.VARIABLE) {
2954            IVariableBinding variableBinding= (IVariableBinding)binding;
2955            if (variableBinding.isField()) {
2956                int constantModifier= IModifierConstants.ACC_STATIC | IModifierConstants.ACC_FINAL;
2957                boolean isConstant= (variableBinding.getModifiers() & constantModifier) == constantModifier;
2958                if (isConstant)
2959                    return fMarkConstantOccurrences;
2960                else
2961                    return fMarkFieldOccurrences;
2962            }
2963
2964            return fMarkLocalVariableypeOccurrences;
2965        }
2966
2967        return false;
2968    }
2969
2970    void removeOccurrenceAnnotations() {
2971        fMarkOccurrenceModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
2972        fMarkOccurrenceTargetRegion= null;
2973
2974        IDocumentProvider documentProvider= getDocumentProvider();
2975        if (documentProvider == null)
2976            return;
2977
2978        IAnnotationModel annotationModel= documentProvider.getAnnotationModel(getEditorInput());
2979        if (annotationModel == null || fOccurrenceAnnotations == null)
2980            return;
2981
2982        synchronized (getLockObject(annotationModel)) {
2983            if (annotationModel instanceof IAnnotationModelExtension) {
2984                ((IAnnotationModelExtension)annotationModel).replaceAnnotations(fOccurrenceAnnotations, null);
2985            } else {
2986                for (int i= 0, length= fOccurrenceAnnotations.length; i < length; i++)
2987                    annotationModel.removeAnnotation(fOccurrenceAnnotations[i]);
2988            }
2989            fOccurrenceAnnotations= null;
2990        }
2991    }
2992
2993    protected void uninstallOverrideIndicator() {
2994        if (fOverrideIndicatorManager != null) {
2995            fOverrideIndicatorManager.removeAnnotations();
2996            fOverrideIndicatorManager= null;
2997        }
2998    }
2999
3000    protected void installOverrideIndicator(boolean provideAST) {
3001        uninstallOverrideIndicator();
3002        IAnnotationModel model= getDocumentProvider().getAnnotationModel(getEditorInput());
3003        final IJavaElement inputElement= getInputJavaElement();
3004
3005        if (model == null || inputElement == null)
3006            return;
3007
3008        fOverrideIndicatorManager= new OverrideIndicatorManager(model, inputElement, null);
3009        
3010        if (provideAST) {
3011            CompilationUnit ast= JavaPlugin.getDefault().getASTProvider().getAST(inputElement, ASTProvider.WAIT_ACTIVE_ONLY, getProgressMonitor());
3012            fOverrideIndicatorManager.reconciled(ast, true, getProgressMonitor());
3013        }
3014    }
3015
3016    /**
3017     * Tells whether override indicators are shown.
3018     *
3019     * @return <code>true</code> if the override indicators are shown
3020     * @since 3.0
3021     */

3022    protected boolean isShowingOverrideIndicators() {
3023        AnnotationPreference preference= getAnnotationPreferenceLookup().getAnnotationPreference(OverrideIndicatorManager.ANNOTATION_TYPE);
3024        IPreferenceStore store= getPreferenceStore();
3025        return getBoolean(store, preference.getHighlightPreferenceKey())
3026            || getBoolean(store, preference.getVerticalRulerPreferenceKey())
3027            || getBoolean(store, preference.getOverviewRulerPreferenceKey())
3028            || getBoolean(store, preference.getTextPreferenceKey());
3029    }
3030
3031    /**
3032     * Returns the boolean preference for the given key.
3033     *
3034     * @param store the preference store
3035     * @param key the preference key
3036     * @return <code>true</code> if the key exists in the store and its value is <code>true</code>
3037     * @since 3.0
3038     */

3039    private boolean getBoolean(IPreferenceStore store, String JavaDoc key) {
3040        return key != null && store.getBoolean(key);
3041    }
3042
3043    /**
3044     * Determines whether the preference change encoded by the given event
3045     * changes the override indication.
3046     *
3047     * @param event the event to be investigated
3048     * @return <code>true</code> if event causes a change
3049     * @since 3.0
3050     */

3051    protected boolean affectsOverrideIndicatorAnnotations(PropertyChangeEvent event) {
3052        String JavaDoc key= event.getProperty();
3053        AnnotationPreference preference= getAnnotationPreferenceLookup().getAnnotationPreference(OverrideIndicatorManager.ANNOTATION_TYPE);
3054        if (key == null || preference == null)
3055            return false;
3056
3057        return key.equals(preference.getHighlightPreferenceKey())
3058            || key.equals(preference.getVerticalRulerPreferenceKey())
3059            || key.equals(preference.getOverviewRulerPreferenceKey())
3060            || key.equals(preference.getTextPreferenceKey());
3061    }
3062
3063    /**
3064     * @return <code>true</code> if Semantic Highlighting is enabled.
3065     *
3066     * @since 3.0
3067     */

3068    private boolean isSemanticHighlightingEnabled() {
3069        return SemanticHighlightings.isEnabled(getPreferenceStore());
3070    }
3071
3072    /**
3073     * Install Semantic Highlighting.
3074     *
3075     * @since 3.0
3076     */

3077    private void installSemanticHighlighting() {
3078        if (fSemanticManager == null) {
3079            fSemanticManager= new SemanticHighlightingManager();
3080            fSemanticManager.install(this, (JavaSourceViewer) getSourceViewer(), JavaPlugin.getDefault().getJavaTextTools().getColorManager(), getPreferenceStore());
3081        }
3082    }
3083
3084    /**
3085     * Uninstall Semantic Highlighting.
3086     *
3087     * @since 3.0
3088     */

3089    private void uninstallSemanticHighlighting() {
3090        if (fSemanticManager != null) {
3091            fSemanticManager.uninstall();
3092            fSemanticManager= null;
3093        }
3094    }
3095
3096    /**
3097     * Returns the Java element wrapped by this editors input.
3098     *
3099     * @return the Java element wrapped by this editors input.
3100     * @since 3.0
3101     */

3102    protected IJavaElement getInputJavaElement() {
3103        return EditorUtility.getEditorInputJavaElement(this, false);
3104    }
3105
3106    protected void updateStatusLine() {
3107        ITextSelection selection= (ITextSelection) getSelectionProvider().getSelection();
3108        Annotation annotation= getAnnotation(selection.getOffset(), selection.getLength());
3109        setStatusLineErrorMessage(null);
3110        setStatusLineMessage(null);
3111        if (annotation != null) {
3112            updateMarkerViews(annotation);
3113            if (annotation instanceof IJavaAnnotation && ((IJavaAnnotation) annotation).isProblem())
3114                setStatusLineMessage(annotation.getText());
3115        }
3116    }
3117
3118    /**
3119     * Jumps to the matching bracket.
3120     */

3121    public void gotoMatchingBracket() {
3122
3123        ISourceViewer sourceViewer= getSourceViewer();
3124        IDocument document= sourceViewer.getDocument();
3125        if (document == null)
3126            return;
3127
3128        IRegion selection= getSignedSelection(sourceViewer);
3129
3130        int selectionLength= Math.abs(selection.getLength());
3131        if (selectionLength > 1) {
3132            setStatusLineErrorMessage(JavaEditorMessages.GotoMatchingBracket_error_invalidSelection);
3133            sourceViewer.getTextWidget().getDisplay().beep();
3134            return;
3135        }
3136
3137        // #26314
3138
int sourceCaretOffset= selection.getOffset() + selection.getLength();
3139        if (isSurroundedByBrackets(document, sourceCaretOffset))
3140            sourceCaretOffset -= selection.getLength();
3141
3142        IRegion region= fBracketMatcher.match(document, sourceCaretOffset);
3143        if (region == null) {
3144            setStatusLineErrorMessage(JavaEditorMessages.GotoMatchingBracket_error_noMatchingBracket);
3145            sourceViewer.getTextWidget().getDisplay().beep();
3146            return;
3147        }
3148
3149        int offset= region.getOffset();
3150        int length= region.getLength();
3151
3152        if (length < 1)
3153            return;
3154
3155        int anchor= fBracketMatcher.getAnchor();
3156        // http://dev.eclipse.org/bugs/show_bug.cgi?id=34195
3157
int targetOffset= (ICharacterPairMatcher.RIGHT == anchor) ? offset + 1: offset + length;
3158
3159        boolean visible= false;
3160        if (sourceViewer instanceof ITextViewerExtension5) {
3161            ITextViewerExtension5 extension= (ITextViewerExtension5) sourceViewer;
3162            visible= (extension.modelOffset2WidgetOffset(targetOffset) > -1);
3163        } else {
3164            IRegion visibleRegion= sourceViewer.getVisibleRegion();
3165            // http://dev.eclipse.org/bugs/show_bug.cgi?id=34195
3166
visible= (targetOffset >= visibleRegion.getOffset() && targetOffset <= visibleRegion.getOffset() + visibleRegion.getLength());
3167        }
3168
3169        if (!visible) {
3170            setStatusLineErrorMessage(JavaEditorMessages.GotoMatchingBracket_error_bracketOutsideSelectedElement);
3171            sourceViewer.getTextWidget().getDisplay().beep();
3172            return;
3173        }
3174
3175        if (selection.getLength() < 0)
3176            targetOffset -= selection.getLength();
3177
3178        sourceViewer.setSelectedRange(targetOffset, selection.getLength());
3179        sourceViewer.revealRange(targetOffset, selection.getLength());
3180    }
3181
3182    /**
3183     * Returns the signed current selection.
3184     * The length will be negative if the resulting selection
3185     * is right-to-left (RtoL).
3186     * <p>
3187     * The selection offset is model based.
3188     * </p>
3189     *
3190     * @param sourceViewer the source viewer
3191     * @return a region denoting the current signed selection, for a resulting RtoL selections length is < 0
3192     */

3193    protected IRegion getSignedSelection(ISourceViewer sourceViewer) {
3194        StyledText text= sourceViewer.getTextWidget();
3195        Point selection= text.getSelectionRange();
3196
3197        if (text.getCaretOffset() == selection.x) {
3198            selection.x= selection.x + selection.y;
3199            selection.y= -selection.y;
3200        }
3201
3202        selection.x= widgetOffset2ModelOffset(sourceViewer, selection.x);
3203
3204        return new Region(selection.x, selection.y);
3205    }
3206
3207    /**
3208     * Returns the cached selected range, which allows
3209     * to query it from a non-UI thread.
3210     * <p>
3211     * The result might be outdated if queried from a non-UI thread.</em></p>
3212     *
3213     * @return the caret offset in the master document
3214     * @see ITextViewer#getSelectedRange()
3215     * @since 3.3
3216     */

3217    public Point getCachedSelectedRange() {
3218        return fCachedSelectedRange;
3219    }
3220
3221    /*
3222     * @see org.eclipse.ui.texteditor.AbstractTextEditor#handleCursorPositionChanged()
3223     * @since 3.3
3224     */

3225    protected void handleCursorPositionChanged() {
3226        super.handleCursorPositionChanged();
3227        fCachedSelectedRange= getViewer().getSelectedRange();
3228    }
3229
3230    private static boolean isBracket(char character) {
3231        for (int i= 0; i != BRACKETS.length; ++i)
3232            if (character == BRACKETS[i])
3233                return true;
3234        return false;
3235    }
3236
3237    private static boolean isSurroundedByBrackets(IDocument document, int offset) {
3238        if (offset == 0 || offset == document.getLength())
3239            return false;
3240
3241        try {
3242            return
3243                isBracket(document.getChar(offset - 1)) &&
3244                isBracket(document.getChar(offset));
3245
3246        } catch (BadLocationException e) {
3247            return false;
3248        }
3249    }
3250
3251    /**
3252     * {@inheritDoc}
3253     * <p>
3254     * Overrides the default implementation to handle {@link IJavaAnnotation}.
3255     * </p>
3256     *
3257     * @param offset the region offset
3258     * @param length the region length
3259     * @param forward <code>true</code> for forwards, <code>false</code> for backward
3260     * @param annotationPosition the position of the found annotation
3261     * @return the found annotation
3262     * @since 3.2
3263     */

3264    protected Annotation findAnnotation(final int offset, final int length, boolean forward, Position annotationPosition) {
3265
3266        Annotation nextAnnotation= null;
3267        Position nextAnnotationPosition= null;
3268        Annotation containingAnnotation= null;
3269        Position containingAnnotationPosition= null;
3270        boolean currentAnnotation= false;
3271
3272        IDocument document= getDocumentProvider().getDocument(getEditorInput());
3273        int endOfDocument= document.getLength();
3274        int distance= Integer.MAX_VALUE;
3275
3276        IAnnotationModel model= getDocumentProvider().getAnnotationModel(getEditorInput());
3277        Iterator e= new JavaAnnotationIterator(model, true, true);
3278        while (e.hasNext()) {
3279            Annotation a= (Annotation) e.next();
3280            if ((a instanceof IJavaAnnotation) && ((IJavaAnnotation)a).hasOverlay() || !isNavigationTarget(a))
3281                continue;
3282
3283            Position p= model.getPosition(a);
3284            if (p == null)
3285                continue;
3286
3287            if (forward && p.offset == offset || !forward && p.offset + p.getLength() == offset + length) {// || p.includes(offset)) {
3288
if (containingAnnotation == null || (forward && p.length >= containingAnnotationPosition.length || !forward && p.length >= containingAnnotationPosition.length)) {
3289                    containingAnnotation= a;
3290                    containingAnnotationPosition= p;
3291                    currentAnnotation= p.length == length;
3292                }
3293            } else {
3294                int currentDistance= 0;
3295
3296                if (forward) {
3297                    currentDistance= p.getOffset() - offset;
3298                    if (currentDistance < 0)
3299                        currentDistance= endOfDocument + currentDistance;
3300
3301                    if (currentDistance < distance || currentDistance == distance && p.length < nextAnnotationPosition.length) {
3302                        distance= currentDistance;
3303                        nextAnnotation= a;
3304                        nextAnnotationPosition= p;
3305                    }
3306                } else {
3307                    currentDistance= offset + length - (p.getOffset() + p.length);
3308                    if (currentDistance < 0)
3309                        currentDistance= endOfDocument + currentDistance;
3310
3311                    if (currentDistance < distance || currentDistance == distance && p.length < nextAnnotationPosition.length) {
3312                        distance= currentDistance;
3313                        nextAnnotation= a;
3314                        nextAnnotationPosition= p;
3315                    }
3316                }
3317            }
3318        }
3319        if (containingAnnotationPosition != null && (!currentAnnotation || nextAnnotation == null)) {
3320            annotationPosition.setOffset(containingAnnotationPosition.getOffset());
3321            annotationPosition.setLength(containingAnnotationPosition.getLength());
3322            return containingAnnotation;
3323        }
3324        if (nextAnnotationPosition != null) {
3325            annotationPosition.setOffset(nextAnnotationPosition.getOffset());
3326            annotationPosition.setLength(nextAnnotationPosition.getLength());
3327        }
3328
3329        return nextAnnotation;
3330    }
3331
3332    /**
3333     * Returns the annotation overlapping with the given range or <code>null</code>.
3334     *
3335     * @param offset the region offset
3336     * @param length the region length
3337     * @return the found annotation or <code>null</code>
3338     * @since 3.0
3339     */

3340    private Annotation getAnnotation(int offset, int length) {
3341        IAnnotationModel model= getDocumentProvider().getAnnotationModel(getEditorInput());
3342        Iterator e= new JavaAnnotationIterator(model, true, false);
3343        while (e.hasNext()) {
3344            Annotation a= (Annotation) e.next();
3345            Position p= model.getPosition(a);
3346            if (p != null && p.overlapsWith(offset, length))
3347                return a;
3348        }
3349        return null;
3350    }
3351
3352    /*
3353     * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#gotoAnnotation(boolean)
3354     * @since 3.2
3355     */

3356    public Annotation gotoAnnotation(boolean forward) {
3357        fSelectionChangedViaGotoAnnotation= true;
3358        return super.gotoAnnotation(forward);
3359    }
3360    
3361    /**
3362     * Computes and returns the source reference that includes the caret and
3363     * serves as provider for the outline page selection and the editor range
3364     * indication.
3365     *
3366     * @return the computed source reference
3367     * @since 3.0
3368     */

3369    protected ISourceReference computeHighlightRangeSourceReference() {
3370        ISourceViewer sourceViewer= getSourceViewer();
3371        if (sourceViewer == null)
3372            return null;
3373
3374        StyledText styledText= sourceViewer.getTextWidget();
3375        if (styledText == null)
3376            return null;
3377
3378        int caret= 0;
3379        if (sourceViewer instanceof ITextViewerExtension5) {
3380            ITextViewerExtension5 extension= (ITextViewerExtension5)sourceViewer;
3381            caret= extension.widgetOffset2ModelOffset(styledText.getCaretOffset());
3382        } else {
3383            int offset= sourceViewer.getVisibleRegion().getOffset();
3384            caret= offset + styledText.getCaretOffset();
3385        }
3386
3387        IJavaElement element= getElementAt(caret, false);
3388
3389        if ( !(element instanceof ISourceReference))
3390            return null;
3391
3392        if (element.getElementType() == IJavaElement.IMPORT_DECLARATION) {
3393
3394            IImportDeclaration declaration= (IImportDeclaration) element;
3395            IImportContainer container= (IImportContainer) declaration.getParent();
3396            ISourceRange srcRange= null;
3397
3398            try {
3399                srcRange= container.getSourceRange();
3400            } catch (JavaModelException e) {
3401            }
3402
3403            if (srcRange != null && srcRange.getOffset() == caret)
3404                return container;
3405        }
3406
3407        return (ISourceReference) element;
3408    }
3409
3410    /**
3411     * Returns the most narrow java element including the given offset.
3412     *
3413     * @param offset the offset inside of the requested element
3414     * @param reconcile <code>true</code> if editor input should be reconciled in advance
3415     * @return the most narrow java element
3416     * @since 3.0
3417     */

3418    protected IJavaElement getElementAt(int offset, boolean reconcile) {
3419        return getElementAt(offset);
3420    }
3421
3422    /*
3423     * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createChangeHover()
3424     */

3425    protected LineChangeHover createChangeHover() {
3426        return new JavaChangeHover(IJavaPartitions.JAVA_PARTITIONING, getOrientation());
3427    }
3428
3429    /*
3430     * @see org.eclipse.ui.texteditor.AbstractTextEditor#createNavigationActions()
3431     */

3432    protected void createNavigationActions() {
3433        super.createNavigationActions();
3434
3435        final StyledText textWidget= getSourceViewer().getTextWidget();
3436
3437        IAction action= new SmartLineStartAction(textWidget, false);
3438        action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_START);
3439        setAction(ITextEditorActionDefinitionIds.LINE_START, action);
3440
3441        action= new SmartLineStartAction(textWidget, true);
3442        action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_LINE_START);
3443        setAction(ITextEditorActionDefinitionIds.SELECT_LINE_START, action);
3444
3445        action= new NavigatePreviousSubWordAction();
3446        action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_PREVIOUS);
3447        setAction(ITextEditorActionDefinitionIds.WORD_PREVIOUS, action);
3448        textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_LEFT, SWT.NULL);
3449
3450        action= new NavigateNextSubWordAction();
3451        action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_NEXT);
3452        setAction(ITextEditorActionDefinitionIds.WORD_NEXT, action);
3453        textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_RIGHT, SWT.NULL);
3454
3455        action= new SelectPreviousSubWordAction();
3456        action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS);
3457        setAction(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS, action);
3458        textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_LEFT, SWT.NULL);
3459
3460        action= new SelectNextSubWordAction();
3461        action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT);
3462        setAction(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT, action);
3463        textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_RIGHT, SWT.NULL);
3464    }
3465
3466    /*
3467     * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createAnnotationRulerColumn(org.eclipse.jface.text.source.CompositeRuler)
3468     * @since 3.2
3469     */

3470    protected IVerticalRulerColumn createAnnotationRulerColumn(CompositeRuler ruler) {
3471        if (!getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER))
3472            return super.createAnnotationRulerColumn(ruler);
3473
3474        AnnotationRulerColumn column= new AnnotationRulerColumn(VERTICAL_RULER_WIDTH, getAnnotationAccess());
3475        column.setHover(new JavaExpandHover(ruler, getAnnotationAccess(), new IDoubleClickListener() {
3476
3477            public void doubleClick(DoubleClickEvent event) {
3478                // for now: just invoke ruler double click action
3479
triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK);
3480            }
3481
3482            private void triggerAction(String JavaDoc actionID) {
3483                IAction action= getAction(actionID);
3484                if (action != null) {
3485                    if (action instanceof IUpdate)
3486                        ((IUpdate) action).update();
3487                    // hack to propagate line change
3488
if (action instanceof ISelectionListener) {
3489                        ((ISelectionListener)action).selectionChanged(null, null);
3490                    }
3491                    if (action.isEnabled())
3492                        action.run();
3493                }
3494            }
3495
3496        }));
3497        
3498        return column;
3499    }
3500
3501    /**
3502     * Returns the folding action group, or <code>null</code> if there is none.
3503     *
3504     * @return the folding action group, or <code>null</code> if there is none
3505     * @since 3.0
3506     */

3507    protected FoldingActionGroup getFoldingActionGroup() {
3508        return fFoldingGroup;
3509    }
3510
3511    /*
3512     * @see org.eclipse.ui.texteditor.AbstractTextEditor#performRevert()
3513     */

3514    protected void performRevert() {
3515        ProjectionViewer projectionViewer= (ProjectionViewer) getSourceViewer();
3516        projectionViewer.setRedraw(false);
3517        try {
3518
3519            boolean projectionMode= projectionViewer.isProjectionMode();
3520            if (projectionMode) {
3521                projectionViewer.disableProjection();
3522                if (fProjectionModelUpdater != null)
3523                    fProjectionModelUpdater.uninstall();
3524            }
3525
3526            super.performRevert();
3527
3528            if (projectionMode) {
3529                if (fProjectionModelUpdater != null)
3530                    fProjectionModelUpdater.install(this, projectionViewer);
3531                projectionViewer.enableProjection();
3532            }
3533
3534        } finally {
3535            projectionViewer.setRedraw(true);
3536        }
3537    }
3538
3539    /*
3540     * @see org.eclipse.ui.texteditor.AbstractTextEditor#rulerContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager)
3541     */

3542    protected void rulerContextMenuAboutToShow(IMenuManager menu) {
3543        super.rulerContextMenuAboutToShow(menu);
3544        IMenuManager foldingMenu= new MenuManager(JavaEditorMessages.Editor_FoldingMenu_name, "projection"); //$NON-NLS-1$
3545
menu.appendToGroup(ITextEditorActionConstants.GROUP_RULERS, foldingMenu);
3546
3547        IAction action= getAction("FoldingToggle"); //$NON-NLS-1$
3548
foldingMenu.add(action);
3549        action= getAction("FoldingExpandAll"); //$NON-NLS-1$
3550
foldingMenu.add(action);
3551        action= getAction("FoldingCollapseAll"); //$NON-NLS-1$
3552
foldingMenu.add(action);
3553        action= getAction("FoldingRestore"); //$NON-NLS-1$
3554
foldingMenu.add(action);
3555        action= getAction("FoldingCollapseMembers"); //$NON-NLS-1$
3556
foldingMenu.add(action);
3557        action= getAction("FoldingCollapseComments"); //$NON-NLS-1$
3558
foldingMenu.add(action);
3559    }
3560
3561    /*
3562     * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#collectContextMenuPreferencePages()
3563     * @since 3.1
3564     */

3565    protected String JavaDoc[] collectContextMenuPreferencePages() {
3566        String JavaDoc[] inheritedPages= super.collectContextMenuPreferencePages();
3567        int length= 10;
3568        String JavaDoc[] result= new String JavaDoc[inheritedPages.length + length];
3569        result[0]= "org.eclipse.jdt.ui.preferences.JavaEditorPreferencePage"; //$NON-NLS-1$
3570
result[1]= "org.eclipse.jdt.ui.preferences.JavaTemplatePreferencePage"; //$NON-NLS-1$
3571
result[2]= "org.eclipse.jdt.ui.preferences.CodeAssistPreferencePage"; //$NON-NLS-1$
3572
result[3]= "org.eclipse.jdt.ui.preferences.CodeAssistPreferenceAdvanced"; //$NON-NLS-1$
3573
result[4]= "org.eclipse.jdt.ui.preferences.JavaEditorHoverPreferencePage"; //$NON-NLS-1$
3574
result[5]= "org.eclipse.jdt.ui.preferences.JavaEditorColoringPreferencePage"; //$NON-NLS-1$
3575
result[6]= "org.eclipse.jdt.ui.preferences.FoldingPreferencePage"; //$NON-NLS-1$
3576
result[7]= "org.eclipse.jdt.ui.preferences.MarkOccurrencesPreferencePage"; //$NON-NLS-1$
3577
result[8]= "org.eclipse.jdt.ui.preferences.SmartTypingPreferencePage"; //$NON-NLS-1$
3578
result[9]= "org.eclipse.jdt.ui.preferences.SaveParticipantPreferencePage"; //$NON-NLS-1$
3579
System.arraycopy(inheritedPages, 0, result, length, inheritedPages.length);
3580        return result;
3581    }
3582    
3583    /*
3584     * @see AbstractTextEditor#getUndoRedoOperationApprover(IUndoContext)
3585     * @since 3.1
3586     */

3587    protected IOperationApprover getUndoRedoOperationApprover(IUndoContext undoContext) {
3588        // since IResource is a more general way to compare java elements, we
3589
// use this as the preferred class for comparing objects.
3590
return new NonLocalUndoUserApprover(undoContext, this, new Object JavaDoc [] { getInputJavaElement() }, IResource.class);
3591    }
3592
3593    /**
3594     * Resets the foldings structure according to the folding
3595     * preferences.
3596     *
3597     * @since 3.2
3598     */

3599    public void resetProjection() {
3600        if (fProjectionModelUpdater != null) {
3601            fProjectionModelUpdater.initialize();
3602        }
3603    }
3604    
3605    /**
3606     * Collapses all foldable members if supported by the folding
3607     * structure provider.
3608     *
3609     * @since 3.2
3610     */

3611    public void collapseMembers() {
3612        if (fProjectionModelUpdater instanceof IJavaFoldingStructureProviderExtension) {
3613            IJavaFoldingStructureProviderExtension extension= (IJavaFoldingStructureProviderExtension) fProjectionModelUpdater;
3614            extension.collapseMembers();
3615        }
3616    }
3617    
3618    /**
3619     * Collapses all foldable comments if supported by the folding
3620     * structure provider.
3621     *
3622     * @since 3.2
3623     */

3624    public void collapseComments() {
3625        if (fProjectionModelUpdater instanceof IJavaFoldingStructureProviderExtension) {
3626            IJavaFoldingStructureProviderExtension extension= (IJavaFoldingStructureProviderExtension) fProjectionModelUpdater;
3627            extension.collapseComments();
3628        }
3629    }
3630}
3631
Popular Tags