|
From: <caw...@us...> - 2006-07-20 00:10:29
|
Revision: 1525 Author: cawilliams Date: 2006-07-19 17:10:25 -0700 (Wed, 19 Jul 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1525&view=rev Log Message: ----------- move the mark occurrences code over to RubyAbstractEditor from RubyEditor (the line between where this stuff goes is very foggy... but I was forced to do this because of what I did next...) made the editor actually listen to user preferences for mark occurrences stuff (set in the new UI page). Turning marking on/off and sticky occurrences already work as expected. There may be a need to actually delineate between which types of occurrences to mark (local vars, fields, method calls, constants, method returns etc.) Modified Paths: -------------- branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java 2006-07-20 00:07:27 UTC (rev 1524) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java 2006-07-20 00:10:25 UTC (rev 1525) @@ -1,20 +1,42 @@ package org.rubypeople.rdt.internal.ui.rubyeditor; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentCommand; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension4; +import org.eclipse.jface.text.IDocumentListener; +import org.eclipse.jface.text.ISelectionValidator; +import org.eclipse.jface.text.ISynchronizable; +import org.eclipse.jface.text.ITextInputListener; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.ITextViewerExtension5; import org.eclipse.jface.text.IWidgetTokenKeeper; +import org.eclipse.jface.text.Position; import org.eclipse.jface.text.TextSelection; import org.eclipse.jface.text.contentassist.ContentAssistant; import org.eclipse.jface.text.contentassist.IContentAssistant; +import org.eclipse.jface.text.link.LinkedModeModel; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.IAnnotationModelExtension; import org.eclipse.jface.text.source.IOverviewRuler; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.IVerticalRuler; @@ -22,7 +44,9 @@ import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.ListenerList; import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.IPostSelectionProvider; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; @@ -32,6 +56,7 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IPartService; +import org.eclipse.ui.IWindowListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; @@ -56,6 +81,8 @@ import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.core.formatter.DefaultCodeFormatterConstants; import org.rubypeople.rdt.internal.corext.util.CodeFormatterUtil; +import org.rubypeople.rdt.internal.ti.DefaultOccurrencesFinder; +import org.rubypeople.rdt.internal.ti.IOccurrencesFinder; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.rubyeditor.RubyEditor.ITextConverter; import org.rubypeople.rdt.internal.ui.rubyeditor.RubyEditor.TabConverter; @@ -81,7 +108,7 @@ protected AbstractSelectionChangedListener fOutlineSelectionChangedListener = new OutlineSelectionChangedListener(); private RubyOutlinePage fOutlinePage; /** The editor's tab converter */ - private TabConverter fTabConverter; + private TabConverter fTabConverter; // FIXME The tab conversion stuff should all be in the same class, either this one or RubyEditor /** Preference key for matching brackets */ protected final static String MATCHING_BRACKETS= PreferenceConstants.EDITOR_MATCHING_BRACKETS; @@ -96,8 +123,90 @@ /** The editor's bracket matcher */ protected RubyPairMatcher fBracketMatcher= new RubyPairMatcher(BRACKETS); + + /** + * Holds the current occurrence annotations. + * @since 3.0 + */ + private Annotation[] fOccurrenceAnnotations= null; /** + * Tells whether all occurrences of the element at the + * current caret location are automatically marked in + * this editor. + * @since 3.0 + */ + private boolean fMarkOccurrenceAnnotations; + /** + * Tells whether the occurrence annotations are sticky + * i.e. whether they stay even if there's no valid Java + * element at the current caret position. + * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. + * @since 3.0 + */ + private boolean fStickyOccurrenceAnnotations; + /** + * Tells whether to mark type occurrences in this editor. + * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. + * @since 3.0 + */ + private boolean fMarkTypeOccurrences; + /** + * Tells whether to mark method occurrences in this editor. + * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. + * @since 3.0 + */ + private boolean fMarkMethodOccurrences; + /** + * Tells whether to mark constant occurrences in this editor. + * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. + * @since 3.0 + */ + private boolean fMarkConstantOccurrences; + /** + * Tells whether to mark field occurrences in this editor. + * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. + * @since 3.0 + */ + private boolean fMarkFieldOccurrences; + /** + * Tells whether to mark local variable occurrences in this editor. + * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. + * @since 3.0 + */ + private boolean fMarkLocalVariableypeOccurrences; + /** + * Tells whether to mark method exits in this editor. + * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. + * @since 3.0 + */ + private boolean fMarkMethodExitPoints; + + /** + * The selection used when forcing occurrence marking + * through code. + * @since 3.0 + */ + private ISelection fForcedMarkOccurrencesSelection; + /** + * The document modification stamp at the time when the last + * occurrence marking took place. + * @since 3.1 + */ + //TODO: Do I need to use this? + private long fMarkOccurrenceModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP; + + /** + * The internal shell activation listener for updating occurrences. + */ + private ActivationListener fActivationListener= new ActivationListener(); + private ISelectionChangedListener fPostSelectionListener; + private OccurrencesFinderJob fOccurrencesFinderJob; + /** The occurrences finder job canceler */ + private OccurrencesFinderJobCanceler fOccurrencesFinderJobCanceler; + private IOccurrencesFinder fOccurrencesFinder; + + /** * Creates and returns the preference store for this Ruby editor with the given input. * * @param input The editor input for which to create the preference store @@ -170,6 +279,14 @@ setPreferenceStore(store); RubyTextTools textTools= RubyPlugin.getDefault().getRubyTextTools(); setSourceViewerConfiguration(new RubySourceViewerConfiguration(textTools.getColorManager(), store, this, IRubyPartitions.RUBY_PARTITIONING)); + fMarkOccurrenceAnnotations= store.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES); + fStickyOccurrenceAnnotations= store.getBoolean(PreferenceConstants.EDITOR_STICKY_OCCURRENCES); + fMarkTypeOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES); + fMarkMethodOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES); + fMarkConstantOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES); + fMarkFieldOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES); + fMarkLocalVariableypeOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES); + fMarkMethodExitPoints= store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS); } /* @@ -193,7 +310,14 @@ */ public void dispose() { super.dispose(); + // cancel possible running computation + fMarkOccurrenceAnnotations= false; + uninstallOccurrencesFinder(); + if (fActivationListener != null) { + PlatformUI.getWorkbench().removeWindowListener(fActivationListener); + fActivationListener= null; + } } public Object getAdapter(Class required) { @@ -244,7 +368,48 @@ } try { - + boolean newBooleanValue= false; + Object newValue= event.getNewValue(); + if (newValue != null) + newBooleanValue= Boolean.valueOf(newValue.toString()).booleanValue(); + if (PreferenceConstants.EDITOR_MARK_OCCURRENCES.equals(property)) { + if (newBooleanValue != fMarkOccurrenceAnnotations) { + fMarkOccurrenceAnnotations= newBooleanValue; + if (!fMarkOccurrenceAnnotations) + uninstallOccurrencesFinder(); + else + installOccurrencesFinder(true); + } + return; + } + if (PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES.equals(property)) { + fMarkTypeOccurrences= newBooleanValue; + return; + } + if (PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES.equals(property)) { + fMarkMethodOccurrences= newBooleanValue; + return; + } + if (PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES.equals(property)) { + fMarkConstantOccurrences= newBooleanValue; + return; + } + if (PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES.equals(property)) { + fMarkFieldOccurrences= newBooleanValue; + return; + } + if (PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES.equals(property)) { + fMarkLocalVariableypeOccurrences= newBooleanValue; + return; + } + if (PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS.equals(property)) { + fMarkMethodExitPoints= newBooleanValue; + return; + } + if (PreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property)) { + fStickyOccurrenceAnnotations= newBooleanValue; + return; + } AdaptedSourceViewer sourceViewer= (AdaptedSourceViewer) getSourceViewer(); if (sourceViewer == null) return; @@ -285,8 +450,7 @@ adjustHighlightRange(selection.x, selection.y); } } - - } + } } private int getTabSize() { @@ -348,6 +512,11 @@ if (isTabConversionEnabled()) startTabConversion(); + + if (fMarkOccurrenceAnnotations) + installOccurrencesFinder(false); + + PlatformUI.getWorkbench().addWindowListener(fActivationListener); } private boolean isTabConversionEnabled() { @@ -625,6 +794,10 @@ protected abstract IRubyElement getElementAt(int offset); + public final ISourceViewer getViewer() { + return getSourceViewer(); + } + /** * Adapts an options {@link IEclipsePreferences} to {@link org.eclipse.jface.preference.IPreferenceStore}. * <p> @@ -993,4 +1166,389 @@ } } + /** + * Internal activation listener. + * @since 3.0 + */ + private class ActivationListener implements IWindowListener { + + /* + * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow) + * @since 3.1 + */ + public void windowActivated(IWorkbenchWindow window) { + if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations && isActivePart()) { + fForcedMarkOccurrencesSelection= getSelectionProvider().getSelection(); + updateOccurrenceAnnotations((ITextSelection)fForcedMarkOccurrencesSelection); + } + } + + /* + * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow) + * @since 3.1 + */ + public void windowDeactivated(IWorkbenchWindow window) { + if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations && isActivePart()) + removeOccurrenceAnnotations(); + } + + /* + * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow) + * @since 3.1 + */ + public void windowClosed(IWorkbenchWindow window) { + } + + /* + * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow) + * @since 3.1 + */ + public void windowOpened(IWorkbenchWindow window) { + } + } + + /** + * Cancels the occurrences finder job upon document changes. + * + * @since 3.0 + */ + class OccurrencesFinderJobCanceler implements IDocumentListener, ITextInputListener { + + public void install() { + ISourceViewer sourceViewer= getSourceViewer(); + if (sourceViewer == null) + return; + + StyledText text= sourceViewer.getTextWidget(); + if (text == null || text.isDisposed()) + return; + + sourceViewer.addTextInputListener(this); + + IDocument document= sourceViewer.getDocument(); + if (document != null) + document.addDocumentListener(this); + } + + public void uninstall() { + ISourceViewer sourceViewer= getSourceViewer(); + if (sourceViewer != null) + sourceViewer.removeTextInputListener(this); + + IDocumentProvider documentProvider= getDocumentProvider(); + if (documentProvider != null) { + IDocument document= documentProvider.getDocument(getEditorInput()); + if (document != null) + document.removeDocumentListener(this); + } + } + + + /* + * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent) + */ + public void documentAboutToBeChanged(DocumentEvent event) { + if (fOccurrencesFinderJob != null) + fOccurrencesFinderJob.doCancel(); + } + + /* + * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent) + */ + public void documentChanged(DocumentEvent event) { + } + + /* + * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument) + */ + public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { + if (oldInput == null) + return; + + oldInput.removeDocumentListener(this); + } + + /* + * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument) + */ + public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { + if (newInput == null) + return; + newInput.addDocumentListener(this); + } + } + + /** + * Finds and marks occurrence annotations. + * + * @since 3.0 + */ + class OccurrencesFinderJob extends Job { + + private IDocument fDocument; + private ISelection fSelection; + private ISelectionValidator fPostSelectionValidator; + private boolean fCanceled= false; + private IProgressMonitor fProgressMonitor; + private Position[] fPositions; + + public OccurrencesFinderJob(IDocument document, Position[] positions, ISelection selection) { + //TODO: Refactor job name to resource string somewhere + super("OccurrencesFinderJob"); + fDocument= document; + fSelection= selection; + fPositions= positions; + + if (getSelectionProvider() instanceof ISelectionValidator) + fPostSelectionValidator= (ISelectionValidator)getSelectionProvider(); + } + + // cannot use cancel() because it is declared final + void doCancel() { + fCanceled= true; + cancel(); + } + + private boolean isCanceled() { + return fCanceled || fProgressMonitor.isCanceled() + || fPostSelectionValidator != null && !(fPostSelectionValidator.isValid(fSelection) || fForcedMarkOccurrencesSelection == fSelection) + || LinkedModeModel.hasInstalledModel(fDocument); + } + + /* + * @see Job#run(org.eclipse.core.runtime.IProgressMonitor) + */ + public IStatus run(IProgressMonitor progressMonitor) { + + fProgressMonitor= progressMonitor; + + if (isCanceled()) + return Status.CANCEL_STATUS; + + ITextViewer textViewer= getViewer(); + if (textViewer == null) + return Status.CANCEL_STATUS; + + IDocument document= textViewer.getDocument(); + if (document == null) + return Status.CANCEL_STATUS; + + IDocumentProvider documentProvider= getDocumentProvider(); + if (documentProvider == null) + return Status.CANCEL_STATUS; + + IAnnotationModel annotationModel= documentProvider.getAnnotationModel(getEditorInput()); + if (annotationModel == null) + return Status.CANCEL_STATUS; + + // Add occurrence annotations + int length= fPositions.length; + Map annotationMap= new HashMap(length); + for (int i= 0; i < length; i++) { + + if (isCanceled()) + return Status.CANCEL_STATUS; + + String message; + Position position= fPositions[i]; + + // Create & add annotation + try { + message= document.get(position.offset, position.length); + } catch (BadLocationException ex) { + // Skip this match + continue; + } + annotationMap.put( + new Annotation("org.eclipse.jdt.ui.occurrences", false, message), //$NON-NLS-1$ + position); + } + + if (isCanceled()) + return Status.CANCEL_STATUS; + + synchronized (getLockObject(annotationModel)) { + if (annotationModel instanceof IAnnotationModelExtension) { + ((IAnnotationModelExtension)annotationModel).replaceAnnotations(fOccurrenceAnnotations, annotationMap); + } else { + removeOccurrenceAnnotations(); + Iterator iter= annotationMap.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry mapEntry= (Map.Entry)iter.next(); + annotationModel.addAnnotation((Annotation)mapEntry.getKey(), (Position)mapEntry.getValue()); + } + } + fOccurrenceAnnotations= (Annotation[])annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]); + } + + return Status.OK_STATUS; + } + } + + /** + * Updates the occurrences annotations based + * on the current selection. + * + * @param selection the text selection + */ + protected void updateOccurrenceAnnotations(ITextSelection selection) { + + if (fOccurrencesFinderJob != null) + fOccurrencesFinderJob.cancel(); + + if (!fMarkOccurrenceAnnotations) + return; + + if (selection == null) + return; + + IDocument document= getDocumentProvider().getDocument(getEditorInput()); + String source = document.get(); + + // Search for occurrences + fOccurrencesFinder.initialize(source, selection.getOffset(), selection.getLength()); + List<Position> matches = fOccurrencesFinder.perform(); + + if (matches.isEmpty()) { + if (!fStickyOccurrenceAnnotations) { + removeOccurrenceAnnotations(); + } + return; + } else { + // Convert to array + //TODO: Update IOccurrencesFinder interface to return an array of Position + Position[] positions = new Position[matches.size()]; + int i = 0; + for (Position match : matches) { + positions[i++] = match; + } + + // Mark occurrences + fOccurrencesFinderJob= new OccurrencesFinderJob(document, positions, selection); + //fOccurrencesFinderJob.setPriority(Job.DECORATE); + //fOccurrencesFinderJob.setSystem(true); + //fOccurrencesFinderJob.schedule(); + fOccurrencesFinderJob.run(new NullProgressMonitor()); + } + } + + protected void installOccurrencesFinder(boolean forceUpdate) { + fMarkOccurrenceAnnotations= true; + + fOccurrencesFinder = new DefaultOccurrencesFinder(); + + fPostSelectionListener = new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + updateOccurrenceAnnotations((ITextSelection)event.getSelection()); + } + }; + + IPostSelectionProvider postSelectionProvider = (IPostSelectionProvider)getSourceViewer().getSelectionProvider(); + postSelectionProvider.addPostSelectionChangedListener(fPostSelectionListener); + + if (forceUpdate && getSelectionProvider() != null) { + fForcedMarkOccurrencesSelection= getSelectionProvider().getSelection(); + updateOccurrenceAnnotations((ITextSelection)fForcedMarkOccurrencesSelection); + } + + if (fOccurrencesFinderJobCanceler == null) { + fOccurrencesFinderJobCanceler= new OccurrencesFinderJobCanceler(); + fOccurrencesFinderJobCanceler.install(); + } + } + + protected void uninstallOccurrencesFinder() { + fMarkOccurrenceAnnotations= false; + + if (fOccurrencesFinderJob != null) { + fOccurrencesFinderJob.cancel(); + fOccurrencesFinderJob= null; + } + + if (fOccurrencesFinderJobCanceler != null) { + fOccurrencesFinderJobCanceler.uninstall(); + fOccurrencesFinderJobCanceler= null; + } + + if (fPostSelectionListener != null) { + IPostSelectionProvider postSelectionProvider = (IPostSelectionProvider)getSourceViewer().getSelectionProvider(); + postSelectionProvider.removePostSelectionChangedListener(fPostSelectionListener); + fPostSelectionListener = null; + } + + removeOccurrenceAnnotations(); + } + + protected boolean isMarkingOccurrences() { + return fMarkOccurrenceAnnotations; + } + +// boolean markOccurrencesOfType(IBinding binding) { +// +// if (binding == null) +// return false; +// +// int kind= binding.getKind(); +// +// if (fMarkTypeOccurrences && kind == IBinding.TYPE) +// return true; +// +// if (fMarkMethodOccurrences && kind == IBinding.METHOD) +// return true; +// +// if (kind == IBinding.VARIABLE) { +// IVariableBinding variableBinding= (IVariableBinding)binding; +// if (variableBinding.isField()) { +// int constantModifier= IModifierConstants.ACC_STATIC | IModifierConstants.ACC_FINAL; +// boolean isConstant= (variableBinding.getModifiers() & constantModifier) == constantModifier; +// if (isConstant) +// return fMarkConstantOccurrences; +// else +// return fMarkFieldOccurrences; +// } +// +// return fMarkLocalVariableypeOccurrences; +// } +// +// return false; +// } + + void removeOccurrenceAnnotations() { + fMarkOccurrenceModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP; + + IDocumentProvider documentProvider= getDocumentProvider(); + if (documentProvider == null) + return; + + IAnnotationModel annotationModel= documentProvider.getAnnotationModel(getEditorInput()); + if (annotationModel == null || fOccurrenceAnnotations == null) + return; + + synchronized (getLockObject(annotationModel)) { + if (annotationModel instanceof IAnnotationModelExtension) { + ((IAnnotationModelExtension)annotationModel).replaceAnnotations(fOccurrenceAnnotations, null); + } else { + for (int i= 0, length= fOccurrenceAnnotations.length; i < length; i++) + annotationModel.removeAnnotation(fOccurrenceAnnotations[i]); + } + fOccurrenceAnnotations= null; + } + } + + + /** + * Returns the lock object for the given annotation model. + * + * @param annotationModel the annotation model + * @return the annotation model's lock object + * @since 3.0 + */ + private Object getLockObject(IAnnotationModel annotationModel) { + if (annotationModel instanceof ISynchronizable) { + Object lock= ((ISynchronizable)annotationModel).getLockObject(); + if (lock != null) + return lock; + } + return annotationModel; + } } \ No newline at end of file Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java 2006-07-20 00:07:27 UTC (rev 1524) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java 2006-07-20 00:10:25 UTC (rev 1525) @@ -122,6 +122,7 @@ import org.rubypeople.rdt.ui.actions.IRubyEditorActionDefinitionIds; import org.rubypeople.rdt.ui.actions.RubyActionGroup; import org.rubypeople.rdt.ui.actions.SurroundWithBeginRescueAction; +import org.rubypeople.rdt.ui.text.RubyTextTools; import org.rubypeople.rdt.ui.text.folding.IRubyFoldingStructureProvider; import org.rubypeople.rdt.ui.text.folding.IRubyFoldingStructureProviderExtension; @@ -181,108 +182,8 @@ private FoldingActionGroup fFoldingGroup; private BracketInserter fBracketInserter = new BracketInserter(); - - /** - * Holds the current occurrence annotations. - * @since 3.0 - */ - private Annotation[] fOccurrenceAnnotations= null; - /** - * Tells whether all occurrences of the element at the - * current caret location are automatically marked in - * this editor. - * @since 3.0 - */ - private boolean fMarkOccurrenceAnnotations; - /** - * Tells whether the occurrence annotations are sticky - * i.e. whether they stay even if there's no valid Java - * element at the current caret position. - * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. - * @since 3.0 - */ - private boolean fStickyOccurrenceAnnotations; -// /** -// * Tells whether to mark type occurrences in this editor. -// * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. -// * @since 3.0 -// */ -// private boolean fMarkTypeOccurrences; -// /** -// * Tells whether to mark method occurrences in this editor. -// * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. -// * @since 3.0 -// */ -// private boolean fMarkMethodOccurrences; -// /** -// * Tells whether to mark constant occurrences in this editor. -// * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. -// * @since 3.0 -// */ -// private boolean fMarkConstantOccurrences; -// /** -// * Tells whether to mark field occurrences in this editor. -// * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. -// * @since 3.0 -// */ -// private boolean fMarkFieldOccurrences; -// /** -// * Tells whether to mark local variable occurrences in this editor. -// * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. -// * @since 3.0 -// */ -// private boolean fMarkLocalVariableypeOccurrences; -// /** -// * Tells whether to mark exception occurrences in this editor. -// * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. -// * @since 3.0 -// */ -// private boolean fMarkExceptions; -// /** -// * Tells whether to mark method exits in this editor. -// * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. -// * @since 3.0 -// */ -// private boolean fMarkMethodExitPoints; -// -// /** -// * Tells whether to mark targets of <code>break</code> and <code>continue</code> statements in this editor. -// * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. -// * @since 3.2 -// */ -// private boolean fMarkBreakContinueTargets; -// -// /** -// * Tells whether to mark implementors in this editor. -// * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>. -// * @since 3.1 -// */ -// private boolean fMarkImplementors; - /** - * The selection used when forcing occurrence marking - * through code. - * @since 3.0 - */ - private ISelection fForcedMarkOccurrencesSelection; - /** - * The document modification stamp at the time when the last - * occurrence marking took place. - * @since 3.1 - */ - //TODO: Do I need to use this? - private long fMarkOccurrenceModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP; - /** - * The internal shell activation listener for updating occurrences. - */ - private ActivationListener fActivationListener= new ActivationListener(); - private ISelectionChangedListener fPostSelectionListener; - private OccurrencesFinderJob fOccurrencesFinderJob; - /** The occurrences finder job canceler */ - private OccurrencesFinderJobCanceler fOccurrencesFinderJobCanceler; - private IOccurrencesFinder fOccurrencesFinder; - public RubyEditor() { super(); setDocumentProvider(RubyPlugin.getDefault().getRubyDocumentProvider()); @@ -350,11 +251,7 @@ actionGroup = new RubyActionGroup(this, ITextEditorActionConstants.GROUP_EDIT); } - - public final ISourceViewer getViewer() { - return getSourceViewer(); - } - + /** * Configures the toggle comment action * @@ -412,31 +309,8 @@ fBracketInserter.setCloseBracesEnabled(closeBraces); fBracketInserter.setCloseStringsEnabled(closeStrings); ((ITextViewerExtension) sourceViewer).prependVerifyKeyListener(fBracketInserter); - - //TODO: Pull these from prefs rather than hardcoded true values - fMarkOccurrenceAnnotations = true; - fStickyOccurrenceAnnotations = false; -// setPreferenceStore(store); -// JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools(); -// setSourceViewerConfiguration(new JavaSourceViewerConfiguration(textTools.getColorManager(), store, this, IJavaPartitions.JAVA_PARTITIONING)); -// fMarkOccurrenceAnnotations= store.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES); -// fStickyOccurrenceAnnotations= store.getBoolean(PreferenceConstants.EDITOR_STICKY_OCCURRENCES); -// fMarkTypeOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES); -// fMarkMethodOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES); -// fMarkConstantOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES); -// fMarkFieldOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES); -// fMarkLocalVariableypeOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES); -// fMarkExceptions= store.getBoolean(PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES); -// fMarkImplementors= store.getBoolean(PreferenceConstants.EDITOR_MARK_IMPLEMENTORS); -// fMarkMethodExitPoints= store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS); -// fMarkBreakContinueTargets= store.getBoolean(PreferenceConstants.EDITOR_MARK_BREAK_CONTINUE_TARGETS); } - - if (fMarkOccurrenceAnnotations) - installOccurrencesFinder(false); - - PlatformUI.getWorkbench().addWindowListener(fActivationListener); } /** @@ -753,16 +627,7 @@ fProjectionSupport.dispose(); fProjectionSupport = null; } - - // cancel possible running computation - fMarkOccurrenceAnnotations= false; - uninstallOccurrencesFinder(); - - if (fActivationListener != null) { - PlatformUI.getWorkbench().removeWindowListener(fActivationListener); - fActivationListener= null; - } - + super.dispose(); } @@ -1716,389 +1581,4 @@ return fFoldingGroup; } - /** - * Internal activation listener. - * @since 3.0 - */ - private class ActivationListener implements IWindowListener { - - /* - * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow) - * @since 3.1 - */ - public void windowActivated(IWorkbenchWindow window) { - if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations && isActivePart()) { - fForcedMarkOccurrencesSelection= getSelectionProvider().getSelection(); - updateOccurrenceAnnotations((ITextSelection)fForcedMarkOccurrencesSelection); - } - } - - /* - * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow) - * @since 3.1 - */ - public void windowDeactivated(IWorkbenchWindow window) { - if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations && isActivePart()) - removeOccurrenceAnnotations(); - } - - /* - * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow) - * @since 3.1 - */ - public void windowClosed(IWorkbenchWindow window) { - } - - /* - * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow) - * @since 3.1 - */ - public void windowOpened(IWorkbenchWindow window) { - } - } - - /** - * Cancels the occurrences finder job upon document changes. - * - * @since 3.0 - */ - class OccurrencesFinderJobCanceler implements IDocumentListener, ITextInputListener { - - public void install() { - ISourceViewer sourceViewer= getSourceViewer(); - if (sourceViewer == null) - return; - - StyledText text= sourceViewer.getTextWidget(); - if (text == null || text.isDisposed()) - return; - - sourceViewer.addTextInputListener(this); - - IDocument document= sourceViewer.getDocument(); - if (document != null) - document.addDocumentListener(this); - } - - public void uninstall() { - ISourceViewer sourceViewer= getSourceViewer(); - if (sourceViewer != null) - sourceViewer.removeTextInputListener(this); - - IDocumentProvider documentProvider= getDocumentProvider(); - if (documentProvider != null) { - IDocument document= documentProvider.getDocument(getEditorInput()); - if (document != null) - document.removeDocumentListener(this); - } - } - - - /* - * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent) - */ - public void documentAboutToBeChanged(DocumentEvent event) { - if (fOccurrencesFinderJob != null) - fOccurrencesFinderJob.doCancel(); - } - - /* - * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent) - */ - public void documentChanged(DocumentEvent event) { - } - - /* - * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument) - */ - public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { - if (oldInput == null) - return; - - oldInput.removeDocumentListener(this); - } - - /* - * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument) - */ - public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { - if (newInput == null) - return; - newInput.addDocumentListener(this); - } - } - - /** - * Finds and marks occurrence annotations. - * - * @since 3.0 - */ - class OccurrencesFinderJob extends Job { - - private IDocument fDocument; - private ISelection fSelection; - private ISelectionValidator fPostSelectionValidator; - private boolean fCanceled= false; - private IProgressMonitor fProgressMonitor; - private Position[] fPositions; - - public OccurrencesFinderJob(IDocument document, Position[] positions, ISelection selection) { - //TODO: Refactor job name to resource string somewhere - super("OccurrencesFinderJob"); - fDocument= document; - fSelection= selection; - fPositions= positions; - - if (getSelectionProvider() instanceof ISelectionValidator) - fPostSelectionValidator= (ISelectionValidator)getSelectionProvider(); - } - - // cannot use cancel() because it is declared final - void doCancel() { - fCanceled= true; - cancel(); - } - - private boolean isCanceled() { - return fCanceled || fProgressMonitor.isCanceled() - || fPostSelectionValidator != null && !(fPostSelectionValidator.isValid(fSelection) || fForcedMarkOccurrencesSelection == fSelection) - || LinkedModeModel.hasInstalledModel(fDocument); - } - - /* - * @see Job#run(org.eclipse.core.runtime.IProgressMonitor) - */ - public IStatus run(IProgressMonitor progressMonitor) { - - fProgressMonitor= progressMonitor; - - if (isCanceled()) - return Status.CANCEL_STATUS; - - ITextViewer textViewer= getViewer(); - if (textViewer == null) - return Status.CANCEL_STATUS; - - IDocument document= textViewer.getDocument(); - if (document == null) - return Status.CANCEL_STATUS; - - IDocumentProvider documentProvider= getDocumentProvider(); - if (documentProvider == null) - return Status.CANCEL_STATUS; - - IAnnotationModel annotationModel= documentProvider.getAnnotationModel(getEditorInput()); - if (annotationModel == null) - return Status.CANCEL_STATUS; - - // Add occurrence annotations - int length= fPositions.length; - Map annotationMap= new HashMap(length); - for (int i= 0; i < length; i++) { - - if (isCanceled()) - return Status.CANCEL_STATUS; - - String message; - Position position= fPositions[i]; - - // Create & add annotation - try { - message= document.get(position.offset, position.length); - } catch (BadLocationException ex) { - // Skip this match - continue; - } - annotationMap.put( - new Annotation("org.eclipse.jdt.ui.occurrences", false, message), //$NON-NLS-1$ - position); - } - - if (isCanceled()) - return Status.CANCEL_STATUS; - - synchronized (getLockObject(annotationModel)) { - if (annotationModel instanceof IAnnotationModelExtension) { - ((IAnnotationModelExtension)annotationModel).replaceAnnotations(fOccurrenceAnnotations, annotationMap); - } else { - removeOccurrenceAnnotations(); - Iterator iter= annotationMap.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry mapEntry= (Map.Entry)iter.next(); - annotationModel.addAnnotation((Annotation)mapEntry.getKey(), (Position)mapEntry.getValue()); - } - } - fOccurrenceAnnotations= (Annotation[])annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]); - } - - return Status.OK_STATUS; - } - } - - /** - * Updates the occurrences annotations based - * on the current selection. - * - * @param selection the text selection - */ - protected void updateOccurrenceAnnotations(ITextSelection selection) { - - if (fOccurrencesFinderJob != null) - fOccurrencesFinderJob.cancel(); - - if (!fMarkOccurrenceAnnotations) - return; - - if (selection == null) - return; - - IDocument document= getDocumentProvider().getDocument(getEditorInput()); - String source = document.get(); - - // Search for occurrences - fOccurrencesFinder.initialize(source, selection.getOffset(), selection.getLength()); - List<Position> matches = fOccurrencesFinder.perform(); - - if (matches.isEmpty()) { - if (!fStickyOccurrenceAnnotations) { - removeOccurrenceAnnotations(); - } - return; - } else { - // Convert to array - //TODO: Update IOccurrencesFinder interface to return an array of Position - Position[] positions = new Position[matches.size()]; - int i = 0; - for (Position match : matches) { - positions[i++] = match; - } - - // Mark occurrences - fOccurrencesFinderJob= new OccurrencesFinderJob(document, positions, selection); - //fOccurrencesFinderJob.setPriority(Job.DECORATE); - //fOccurrencesFinderJob.setSystem(true); - //fOccurrencesFinderJob.schedule(); - fOccurrencesFinderJob.run(new NullProgressMonitor()); - } - } - - protected void installOccurrencesFinder(boolean forceUpdate) { - fMarkOccurrenceAnnotations= true; - - fOccurrencesFinder = new DefaultOccurrencesFinder(); - - fPostSelectionListener = new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - updateOccurrenceAnnotations((ITextSelection)event.getSelection()); - } - }; - - IPostSelectionProvider postSelectionProvider = (IPostSelectionProvider)getSourceViewer().getSelectionProvider(); - postSelectionProvider.addPostSelectionChangedListener(fPostSelectionListener); - - if (forceUpdate && getSelectionProvider() != null) { - fForcedMarkOccurrencesSelection= getSelectionProvider().getSelection(); - updateOccurrenceAnnotations((ITextSelection)fForcedMarkOccurrencesSelection); - } - - if (fOccurrencesFinderJobCanceler == null) { - fOccurrencesFinderJobCanceler= new OccurrencesFinderJobCanceler(); - fOccurrencesFinderJobCanceler.install(); - } - } - - protected void uninstallOccurrencesFinder() { - fMarkOccurrenceAnnotations= false; - - if (fOccurrencesFinderJob != null) { - fOccurrencesFinderJob.cancel(); - fOccurrencesFinderJob= null; - } - - if (fOccurrencesFinderJobCanceler != null) { - fOccurrencesFinderJobCanceler.uninstall(); - fOccurrencesFinderJobCanceler= null; - } - - if (fPostSelectionListener != null) { - IPostSelectionProvider postSelectionProvider = (IPostSelectionProvider)getSourceViewer().getSelectionProvider(); - postSelectionProvider.removePostSelectionChangedListener(fPostSelectionListener); - fPostSelectionListener = null; - } - - removeOccurrenceAnnotations(); - } - - protected boolean isMarkingOccurrences() { - return fMarkOccurrenceAnnotations; - } - -// boolean markOccurrencesOfType(IBinding binding) { -// -// if (binding == null) -// return false; -// -// int kind= binding.getKind(); -// -// if (fMarkTypeOccurrences && kind == IBinding.TYPE) -// return true; -// -// if (fMarkMethodOccurrences && kind == IBinding.METHOD) -// return true; -// -// if (kind == IBinding.VARIABLE) { -// IVariableBinding variableBinding= (IVariableBinding)binding; -// if (variableBinding.isField()) { -// int constantModifier= IModifierConstants.ACC_STATIC | IModifierConstants.ACC_FINAL; -// boolean isConstant= (variableBinding.getModifiers() & constantModifier) == constantModifier; -// if (isConstant) -// return fMarkConstantOccurrences; -// else -// return fMarkFieldOccurrences; -// } -// -// return fMarkLocalVariableypeOccurrences; -// } -// -// return false; -// } - - void removeOccurrenceAnnotations() { - fMarkOccurrenceModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP; - - IDocumentProvider documentProvider= getDocumentProvider(); - if (documentProvider == null) - return; - - IAnnotationModel annotationModel= documentProvider.getAnnotationModel(getEditorInput()); - if (annotationModel == null || fOccurrenceAnnotations == null) - return; - - synchronized (getLockObject(annotationModel)) { - if (annotationModel instanceof IAnnotationModelExtension) { - ((IAnnotationModelExtension)annotationModel).replaceAnnotations(fOccurrenceAnnotations, null); - } else { - for (int i= 0, length= fOccurrenceAnnotations.length; i < length; i++) - annotationModel.removeAnnotation(fOccurrenceAnnotations[i]); - } - fOccurrenceAnnotations= null; - } - } - - /** - * Returns the lock object for the given annotation model. - * - * @param annotationModel the annotation model - * @return the annotation model's lock object - * @since 3.0 - */ - private Object getLockObject(IAnnotationModel annotationModel) { - if (annotationModel instanceof ISynchronizable) { - Object lock= ((ISynchronizable)annotationModel).getLockObject(); - if (lock != null) - return lock; - } - return annotationModel; - } - } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |