/******************************************************************************* * Copyright (c) 2006, 2016 Red Hat, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Red Hat Incorporated - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.autotools.ui.editors; import java.util.ResourceBundle; import org.eclipse.cdt.autotools.core.AutotoolsPlugin; import org.eclipse.cdt.autotools.ui.AutotoolsUIPlugin; import org.eclipse.cdt.autotools.ui.editors.outline.AutoconfContentOutlinePage; import org.eclipse.cdt.autotools.ui.editors.parser.AutoconfElement; import org.eclipse.cdt.autotools.ui.editors.parser.AutoconfMacroDetector; import org.eclipse.cdt.autotools.ui.editors.parser.AutoconfParser; import org.eclipse.cdt.autotools.ui.editors.parser.IAutoconfMacroValidator; import org.eclipse.cdt.internal.autotools.core.AutotoolsPropertyConstants; import org.eclipse.cdt.internal.autotools.ui.editors.autoconf.ProjectionFileUpdater; import org.eclipse.cdt.internal.autotools.ui.editors.automake.IReconcilingParticipant; import org.eclipse.cdt.internal.autotools.ui.editors.automake.MakefileEditorPreferenceConstants; import org.eclipse.cdt.internal.autotools.ui.preferences.AutoconfEditorPreferencePage; import org.eclipse.cdt.internal.autotools.ui.preferences.AutotoolsEditorPreferenceConstants; import org.eclipse.cdt.internal.autotools.ui.preferences.ColorManager; import org.eclipse.cdt.internal.autotools.ui.properties.AutotoolsPropertyManager; import org.eclipse.cdt.internal.autotools.ui.properties.IProjectPropertyListener; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.ListenerList; import org.eclipse.jface.action.Action; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.text.AbstractInformationControlManager; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextHover; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.ITextViewerExtension2; import org.eclipse.jface.text.ITextViewerExtension4; import org.eclipse.jface.text.ITextViewerExtension5; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.information.IInformationProvider; import org.eclipse.jface.text.information.IInformationProviderExtension; import org.eclipse.jface.text.information.IInformationProviderExtension2; import org.eclipse.jface.text.information.InformationPresenter; import org.eclipse.jface.text.rules.RuleBasedScanner; import org.eclipse.jface.text.source.IAnnotationHover; import org.eclipse.jface.text.source.IAnnotationHoverExtension; import org.eclipse.jface.text.source.ILineRange; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.ISourceViewerExtension3; import org.eclipse.jface.text.source.IVerticalRuler; import org.eclipse.jface.text.source.IVerticalRulerInfo; import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel; import org.eclipse.jface.text.source.projection.ProjectionSupport; import org.eclipse.jface.text.source.projection.ProjectionViewer; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.editors.text.TextEditor; import org.eclipse.ui.texteditor.ChainedPreferenceStore; import org.eclipse.ui.texteditor.ContentAssistAction; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; import org.eclipse.ui.texteditor.ResourceAction; import org.eclipse.ui.texteditor.TextEditorAction; import org.eclipse.ui.texteditor.TextOperationAction; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; public class AutoconfEditor extends TextEditor implements IAutotoolsEditor, IProjectPropertyListener { public final static String AUTOCONF_PARTITIONING= "autoconf_partitioning"; //$NON-NLS-1$ private AutoconfPartitionScanner fPartitionScanner; private RuleBasedScanner fCodeScanner; private RuleBasedScanner fMacroCodeScanner; private static volatile AutoconfDocumentProvider fDocumentProvider; private AutoconfElement rootElement; private AutoconfContentOutlinePage outlinePage; private AutoconfParser fParser; private IEditorInput input; private IProject fProject; /** The information provider used to present focusable information shells. */ private InformationPresenter fInformationPresenter; /** * This editor's projection support */ ProjectionSupport fProjectionSupport; ProjectionFileUpdater fProjectionFileUpdater; /** * Reconciling listeners */ private ListenerList<IReconcilingParticipant> fReconcilingListeners = new ListenerList<>(ListenerList.IDENTITY); public AutoconfEditor() { super(); } @Override protected void initializeEditor() { super.initializeEditor(); setDocumentProvider(getAutoconfDocumentProvider()); IPreferenceStore[] stores = new IPreferenceStore[2]; stores[0] = AutotoolsPlugin.getDefault().getPreferenceStore(); stores[1] = EditorsUI.getPreferenceStore(); ChainedPreferenceStore chainedStore = new ChainedPreferenceStore(stores); setPreferenceStore(chainedStore); setSourceViewerConfiguration(new AutoconfSourceViewerConfiguration(chainedStore, this)); AutotoolsEditorPreferenceConstants.initializeDefaultValues(stores[0]); AutoconfEditorPreferencePage.initDefaults(stores[0]); } public static AutoconfDocumentProvider getAutoconfDocumentProvider() { if (fDocumentProvider == null) fDocumentProvider= new AutoconfDocumentProvider(); return fDocumentProvider; } public AutoconfElement getRootElement() { return rootElement; } public void setRootElement(AutoconfElement element) { rootElement = element; } public ISourceViewer getViewer() { return getSourceViewer(); } protected IDocument getInputDocument() { return getDocumentProvider().getDocument(input); } @Override protected void doSetInput(IEditorInput newInput) throws CoreException { // If this editor is for a project file, remove this editor as a property // change listener. if (fProject != null) AutotoolsPropertyManager.getDefault().removeProjectPropertyListener(fProject, this); this.fProject = null; super.doSetInput(newInput); this.input = newInput; if (input instanceof IFileEditorInput) { IFile f = ((IFileEditorInput)input).getFile(); fProject = f.getProject(); // This is a project file. We want to be notified if the Autoconf editor // properties are changed such that the macro versions are changed. AutotoolsPropertyManager.getDefault().addProjectPropertyListener(fProject, this); } getOutlinePage().setInput(input); try { IDocument document = getInputDocument(); setRootElement(reparseDocument(document)); } catch (Exception e) { e.printStackTrace(); } } @SuppressWarnings("unchecked") @Override public <T> T getAdapter(Class<T> required) { if (ProjectionAnnotationModel.class.equals(required)) { if (fProjectionSupport != null) { Object result = fProjectionSupport.getAdapter(getSourceViewer(), required); if (result != null) { return (T) result; } } } else if (IContentOutlinePage.class.equals(required)) { return (T) getOutlinePage(); } return super.getAdapter(required); } public AutoconfContentOutlinePage getOutlinePage() { if (outlinePage == null) { outlinePage= new AutoconfContentOutlinePage(this); if (getEditorInput() != null) outlinePage.setInput(getEditorInput()); } return outlinePage; } /** * Return a scanner for creating Autoconf partitions. * * @return a scanner for creating Autoconf partitions */ public AutoconfParser getAutoconfParser() { if (fParser == null) { AutoconfErrorHandler errorHandler = new AutoconfErrorHandler(input); IAutoconfMacroValidator macroValidator = new AutoconfEditorMacroValidator(this); fParser = new AutoconfParser(errorHandler, new AutoconfMacroDetector(), macroValidator); } return fParser; } /** * Return a scanner for creating Autoconf partitions. * * @return a scanner for creating Autoconf partitions */ public AutoconfPartitionScanner getAutoconfPartitionScanner() { if (fPartitionScanner == null) fPartitionScanner= new AutoconfPartitionScanner(); return fPartitionScanner; } /** * Returns the Autoconf code scanner. * * @return the Autoconf code scanner */ public RuleBasedScanner getAutoconfCodeScanner() { if (fCodeScanner == null) fCodeScanner= new AutoconfCodeScanner(); return fCodeScanner; } /** * Returns the Autoconf code scanner. * * @return the Autoconf code scanner */ public RuleBasedScanner getAutoconfMacroCodeScanner() { if (fMacroCodeScanner == null) fMacroCodeScanner= new AutoconfMacroCodeScanner(); return fMacroCodeScanner; } /** * Returns the preference color, identified by the given preference. */ public static Color getPreferenceColor(String key) { return ColorManager.getDefault().getColor(PreferenceConverter.getColor(AutotoolsPlugin.getDefault().getPreferenceStore(), key)); } @Override public void handleProjectPropertyChanged(IProject project, String property) { if (property.equals(AutotoolsPropertyConstants.AUTOCONF_MACRO_VERSIONING)) { ISourceViewer sourceViewer= getSourceViewer(); if (sourceViewer == null) return; handleVersionChange(sourceViewer); } } /** * Handle the case whereby the Autoconf or Automake macro versions to use * for this project are changed in which case we want to invalidate and reparse * the document. * * @param sourceViewer */ protected void handleVersionChange(ISourceViewer sourceViewer) { sourceViewer.invalidateTextPresentation(); try { IDocument document = getInputDocument(); setRootElement(reparseDocument(document)); } catch (Exception e) { e.printStackTrace(); } } private AutoconfElement reparseDocument(IDocument document) { AutoconfParser parser = getAutoconfParser(); ((AutoconfErrorHandler)parser.getErrorHandler()).removeAllExistingMarkers(); return parser.parse(document); } @Override protected void handlePreferenceStoreChanged(PropertyChangeEvent event) { ISourceViewer sourceViewer= getSourceViewer(); if (sourceViewer == null) return; String property = event.getProperty(); AutoconfCodeScanner scanner = (AutoconfCodeScanner)getAutoconfCodeScanner(); if (scanner != null) { if (scanner.affectsBehavior(event)) { scanner.adaptToPreferenceChange(event); sourceViewer.invalidateTextPresentation(); } } if (AutotoolsEditorPreferenceConstants.AUTOCONF_VERSION.equals(property) || AutotoolsEditorPreferenceConstants.AUTOMAKE_VERSION.equals(property)) { handleVersionChange(sourceViewer); } else if (AutotoolsEditorPreferenceConstants.EDITOR_FOLDING_ENABLED.equals(property)) { if (sourceViewer instanceof ProjectionViewer) { ProjectionViewer projectionViewer= (ProjectionViewer) sourceViewer; if (fProjectionFileUpdater != null) fProjectionFileUpdater.uninstall(); // either freshly enabled or provider changed fProjectionFileUpdater= new ProjectionFileUpdater(); if (fProjectionFileUpdater != null) { fProjectionFileUpdater.install(this, projectionViewer); } } return; } super.handlePreferenceStoreChanged(event); } /** * Information provider used to present focusable information shells. * * @since 3.1.1 */ private static final class InformationProvider implements IInformationProvider, IInformationProviderExtension, IInformationProviderExtension2 { private IRegion fHoverRegion; private Object fHoverInfo; private IInformationControlCreator fControlCreator; InformationProvider(IRegion hoverRegion, Object hoverInfo, IInformationControlCreator controlCreator) { fHoverRegion= hoverRegion; fHoverInfo= hoverInfo; fControlCreator= controlCreator; } @Override public IRegion getSubject(ITextViewer textViewer, int invocationOffset) { return fHoverRegion; } @Override public String getInformation(ITextViewer textViewer, IRegion subject) { return fHoverInfo.toString(); } @Override public Object getInformation2(ITextViewer textViewer, IRegion subject) { return fHoverInfo; } @Override public IInformationControlCreator getInformationPresenterControlCreator() { return fControlCreator; } } /** * This action behaves in two different ways: If there is no current text * hover, the tooltip is displayed using information presenter. If there is * a current text hover, it is converted into a information presenter in * order to make it sticky. * @since 3.1.1 */ class InformationDispatchAction extends TextEditorAction { /** The wrapped text operation action. */ private final TextOperationAction fTextOperationAction; /** * Creates a dispatch action. * * @param resourceBundle the resource bundle * @param prefix the prefix * @param textOperationAction the text operation action */ public InformationDispatchAction(ResourceBundle resourceBundle, String prefix, final TextOperationAction textOperationAction) { super(resourceBundle, prefix, AutoconfEditor.this); if (textOperationAction == null) throw new IllegalArgumentException(); fTextOperationAction= textOperationAction; } @Override public void run() { ISourceViewer sourceViewer= getSourceViewer(); if (sourceViewer == null) { fTextOperationAction.run(); return; } if (sourceViewer instanceof ITextViewerExtension4) { ITextViewerExtension4 extension4= (ITextViewerExtension4) sourceViewer; if (extension4.moveFocusToWidgetToken()) return; } if (sourceViewer instanceof ITextViewerExtension2) { // does a text hover exist? ITextHover textHover= ((ITextViewerExtension2) sourceViewer).getCurrentTextHover(); if (textHover != null && makeTextHoverFocusable(sourceViewer, textHover)) return; } if (sourceViewer instanceof ISourceViewerExtension3) { // does an annotation hover exist? IAnnotationHover annotationHover= ((ISourceViewerExtension3) sourceViewer).getCurrentAnnotationHover(); if (annotationHover != null && makeAnnotationHoverFocusable(sourceViewer, annotationHover)) return; } // otherwise, just display the tooltip //fTextOperationAction.run(); } /** * Tries to make a text hover focusable (or "sticky"). * * @param sourceViewer the source viewer to display the hover over * @param textHover the hover to make focusable * @return <code>true</code> if successful, <code>false</code> otherwise */ @SuppressWarnings("deprecation") private boolean makeTextHoverFocusable(ISourceViewer sourceViewer, ITextHover textHover) { Point hoverEventLocation= ((ITextViewerExtension2) sourceViewer).getHoverEventLocation(); int offset= computeOffsetAtLocation(sourceViewer, hoverEventLocation.x, hoverEventLocation.y); if (offset == -1) return false; try { IRegion hoverRegion= textHover.getHoverRegion(sourceViewer, offset); if (hoverRegion == null) return false; String hoverInfo= textHover.getHoverInfo(sourceViewer, hoverRegion); IInformationControlCreator controlCreator= null; if (textHover instanceof IInformationProviderExtension2) controlCreator= ((IInformationProviderExtension2)textHover).getInformationPresenterControlCreator(); IInformationProvider informationProvider= new InformationProvider(hoverRegion, hoverInfo, controlCreator); fInformationPresenter.setOffset(offset); fInformationPresenter.setAnchor(AbstractInformationControlManager.ANCHOR_BOTTOM); fInformationPresenter.setMargins(6, 6); // default values from AbstractInformationControlManager String contentType= TextUtilities.getContentType(sourceViewer.getDocument(), AutoconfPartitionScanner.AUTOCONF_MACRO, offset, true); fInformationPresenter.setInformationProvider(informationProvider, contentType); fInformationPresenter.showInformation(); return true; } catch (BadLocationException e) { return false; } } /** * Tries to make an annotation hover focusable (or "sticky"). * * @param sourceViewer the source viewer to display the hover over * @param annotationHover the hover to make focusable * @return <code>true</code> if successful, <code>false</code> otherwise */ private boolean makeAnnotationHoverFocusable(ISourceViewer sourceViewer, IAnnotationHover annotationHover) { IVerticalRulerInfo info= getVerticalRuler(); int line= info.getLineOfLastMouseButtonActivity(); if (line == -1) return false; try { // compute the hover information Object hoverInfo; if (annotationHover instanceof IAnnotationHoverExtension) { IAnnotationHoverExtension extension= (IAnnotationHoverExtension) annotationHover; ILineRange hoverLineRange= extension.getHoverLineRange(sourceViewer, line); if (hoverLineRange == null) return false; final int maxVisibleLines= Integer.MAX_VALUE; // allow any number of lines being displayed, as we support scrolling hoverInfo= extension.getHoverInfo(sourceViewer, hoverLineRange, maxVisibleLines); } else { hoverInfo= annotationHover.getHoverInfo(sourceViewer, line); } // hover region: the beginning of the concerned line to place the control right over the line IDocument document= sourceViewer.getDocument(); int offset= document.getLineOffset(line); String contentType= TextUtilities.getContentType(document, AutoconfPartitionScanner.AUTOCONF_MACRO, offset, true); IInformationControlCreator controlCreator= null; // /* // * XXX: This is a hack to avoid API changes at the end of 3.2, // * and should be fixed for 3.3, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=137967 // */ // if ("org.eclipse.jface.text.source.projection.ProjectionAnnotationHover".equals(annotationHover.getClass().getName())) { //$NON-NLS-1$ // controlCreator= new IInformationControlCreator() { // public IInformationControl createInformationControl(Shell shell) { // int shellStyle= SWT.RESIZE | SWT.TOOL | getOrientation(); // int style= SWT.V_SCROLL | SWT.H_SCROLL; // return new SourceViewerInformationControl(shell, shellStyle, style); // } // }; // // } else { if (annotationHover instanceof IInformationProviderExtension2) controlCreator= ((IInformationProviderExtension2) annotationHover).getInformationPresenterControlCreator(); else if (annotationHover instanceof IAnnotationHoverExtension) controlCreator= ((IAnnotationHoverExtension) annotationHover).getHoverControlCreator(); // } IInformationProvider informationProvider= new InformationProvider(new Region(offset, 0), hoverInfo, controlCreator); fInformationPresenter.setOffset(offset); fInformationPresenter.setAnchor(AbstractInformationControlManager.ANCHOR_RIGHT); fInformationPresenter.setMargins(4, 0); // AnnotationBarHoverManager sets (5,0), minus SourceViewer.GAP_SIZE_1 fInformationPresenter.setInformationProvider(informationProvider, contentType); fInformationPresenter.showInformation(); return true; } catch (BadLocationException e) { return false; } } // modified version from TextViewer private int computeOffsetAtLocation(ITextViewer textViewer, int x, int y) { StyledText styledText= textViewer.getTextWidget(); IDocument document= textViewer.getDocument(); if (document == null) return -1; try { int widgetOffset= styledText.getOffsetAtLocation(new Point(x, y)); Point p= styledText.getLocationAtOffset(widgetOffset); if (p.x > x) widgetOffset--; if (textViewer instanceof ITextViewerExtension5) { ITextViewerExtension5 extension= (ITextViewerExtension5) textViewer; return extension.widgetOffset2ModelOffset(widgetOffset); } else { IRegion visibleRegion= textViewer.getVisibleRegion(); return widgetOffset + visibleRegion.getOffset(); } } catch (IllegalArgumentException e) { return -1; } } } /** * Adds the given listener. * Has no effect if an identical listener was not already registered. * * @param listener The reconcile listener to be added */ @Override public final void addReconcilingParticipant(IReconcilingParticipant listener) { synchronized (fReconcilingListeners) { fReconcilingListeners.add(listener); } } /** * Removes the given listener. * Has no effect if an identical listener was not already registered. * * @param listener the reconcile listener to be removed */ final void removeReconcilingParticipant(IReconcilingParticipant listener) { synchronized (fReconcilingListeners) { fReconcilingListeners.remove(listener); } } /* */ public void reconciled() { // Notify listeners for (IReconcilingParticipant listener : fReconcilingListeners) { listener.reconciled(); } } /** * Determines is folding enabled. * @return <code>true</code> if folding is enabled, <code>false</code> otherwise. */ boolean isFoldingEnabled() { return AutotoolsPlugin.getDefault().getPreferenceStore().getBoolean(MakefileEditorPreferenceConstants.EDITOR_FOLDING_ENABLED); } @Override protected void initializeKeyBindingScopes() { setKeyBindingScopes(new String [] { AutotoolsUIPlugin.getUniqueIdentifier() + ".editor.scope" } ); //$NON-NLS-1$ } @Override protected void createActions() { super.createActions(); // TODO: Figure out how to do this later. // fFoldingGroup= new FoldingActionGroup(this, getSourceViewer()); // Sticky hover support ResourceAction resAction= new TextOperationAction(AutoconfEditorMessages.getResourceBundle(), "ShowToolTip.", this, ISourceViewer.INFORMATION, true); //$NON-NLS-1$ resAction= new InformationDispatchAction(AutoconfEditorMessages.getResourceBundle(), "ShowToolTip.", (TextOperationAction) resAction); //$NON-NLS-1$ resAction.setActionDefinitionId(IAutotoolEditorActionDefinitionIds.SHOW_TOOLTIP); setAction("ShowToolTip", resAction); //$NON-NLS-1$ PlatformUI.getWorkbench().getHelpSystem().setHelp(resAction, IAutotoolHelpContextIds.SHOW_TOOLTIP_ACTION); // Content assist Action action = new ContentAssistAction(AutoconfEditorMessages.getResourceBundle(), "ContentAssistProposal.", this); //$NON-NLS-1$ action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); setAction("ContentAssistProposal", action); //$NON-NLS-1$ markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$ PlatformUI.getWorkbench().getHelpSystem().setHelp(action, IAutotoolHelpContextIds.CONTENT_ASSIST); } /** * The <code>AbstractTextEditor</code> implementation of this * <code>IWorkbenchPart</code> method creates the vertical ruler and * source viewer. Subclasses may extend. * * We attach our own mouseDown listener on the menu bar, * and our own listener for cursor/key/selection events to update cursor position in * status bar. * @param parent Parent composite of the control. */ @Override public void createPartControl(Composite parent) { super.createPartControl(parent); // Sticky hover support IInformationControlCreator informationControlCreator= new IInformationControlCreator() { @Override public IInformationControl createInformationControl(Shell shell) { return new DefaultInformationControl(shell, true); } }; fInformationPresenter= new InformationPresenter(informationControlCreator); fInformationPresenter.setSizeConstraints(60, 10, true, true); fInformationPresenter.install(getSourceViewer()); fInformationPresenter.setDocumentPartitioning(AutoconfPartitionScanner.AUTOCONF_MACRO); ProjectionViewer projectionViewer= (ProjectionViewer) getSourceViewer(); fProjectionSupport= new ProjectionSupport(projectionViewer, getAnnotationAccess(), getSharedColors()); fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error"); //$NON-NLS-1$ fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.warning"); //$NON-NLS-1$ fProjectionSupport.install(); if (isFoldingEnabled()) projectionViewer.doOperation(ProjectionViewer.TOGGLE); fProjectionFileUpdater= new ProjectionFileUpdater(); if (fProjectionFileUpdater != null) { fProjectionFileUpdater.install(this, projectionViewer); fProjectionFileUpdater.initialize(); } PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, IAutotoolHelpContextIds.AC_EDITOR_VIEW); // TODO: Do we need the following two lines? // fEditorSelectionChangedListener= new EditorSelectionChangedListener(); // fEditorSelectionChangedListener.install(getSelectionProvider()); } @Override protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { ISourceViewer viewer = new ProjectionViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), styles); // ensure decoration support has been created and configured. getSourceViewerDecorationSupport(viewer); return viewer; } @Override public void dispose() { if (fProjectionFileUpdater != null) { fProjectionFileUpdater.uninstall(); fProjectionFileUpdater= null; } if (fProject != null) { AutotoolsPropertyManager.getDefault().removeProjectPropertyListener(fProject, this); } super.dispose(); } @Override protected void performRevert() { ProjectionViewer projectionViewer= (ProjectionViewer) getSourceViewer(); projectionViewer.setRedraw(false); try { boolean projectionMode= projectionViewer.isProjectionMode(); if (projectionMode) { projectionViewer.disableProjection(); if (fProjectionFileUpdater != null) fProjectionFileUpdater.uninstall(); } super.performRevert(); if (projectionMode) { if (fProjectionFileUpdater != null) fProjectionFileUpdater.install(this, projectionViewer); projectionViewer.enableProjection(); } } finally { projectionViewer.setRedraw(true); } } public IProject getProject() { return this.fProject; } }