| /* |
| * Copyright (c) 2012, the Dart project authors. |
| * |
| * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except |
| * in compliance with the License. You may obtain a copy of the License at |
| * |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.dart.tools.ui.internal.text.editor; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Maps; |
| import com.google.dart.engine.ast.AstNode; |
| import com.google.dart.engine.ast.ClassDeclaration; |
| import com.google.dart.engine.ast.ClassMember; |
| import com.google.dart.engine.ast.CompilationUnit; |
| import com.google.dart.engine.ast.CompilationUnitMember; |
| import com.google.dart.engine.ast.NodeList; |
| import com.google.dart.engine.ast.visitor.NodeLocator; |
| import com.google.dart.engine.context.AnalysisContext; |
| import com.google.dart.engine.element.CompilationUnitElement; |
| import com.google.dart.engine.index.Index; |
| import com.google.dart.engine.sdk.DartSdk; |
| import com.google.dart.engine.sdk.DirectoryBasedDartSdk; |
| import com.google.dart.engine.search.SearchEngine; |
| import com.google.dart.engine.search.SearchEngineFactory; |
| import com.google.dart.engine.services.assist.AssistContext; |
| import com.google.dart.engine.source.FileBasedSource; |
| import com.google.dart.engine.source.Source; |
| import com.google.dart.engine.utilities.source.SourceRange; |
| import com.google.dart.server.generated.types.NavigationRegion; |
| import com.google.dart.server.generated.types.Outline; |
| import com.google.dart.tools.core.DartCore; |
| import com.google.dart.tools.core.DartCoreDebug; |
| import com.google.dart.tools.core.MessageConsole; |
| import com.google.dart.tools.core.analysis.model.AnalysisServerData; |
| import com.google.dart.tools.core.analysis.model.AnalysisServerNavigationListener; |
| import com.google.dart.tools.core.analysis.model.AnalysisServerOutlineListener; |
| import com.google.dart.tools.core.analysis.model.Project; |
| import com.google.dart.tools.core.analysis.model.ProjectManager; |
| import com.google.dart.tools.core.formatter.DefaultCodeFormatterConstants; |
| import com.google.dart.tools.core.model.DartModelException; |
| import com.google.dart.tools.core.model.SourceReference; |
| import com.google.dart.tools.core.pub.PubCacheManager_NEW; |
| import com.google.dart.tools.core.utilities.general.SourceRangeFactory; |
| import com.google.dart.tools.internal.corext.refactoring.util.ExecutionUtils; |
| import com.google.dart.tools.internal.corext.refactoring.util.RunnableEx; |
| import com.google.dart.tools.internal.search.ui.DartSearchActionGroup_NEW; |
| import com.google.dart.tools.internal.search.ui.DartSearchActionGroup_OLD; |
| import com.google.dart.tools.ui.DartToolsPlugin; |
| import com.google.dart.tools.ui.DartX; |
| import com.google.dart.tools.ui.IContextMenuConstants; |
| import com.google.dart.tools.ui.PreferenceConstants; |
| import com.google.dart.tools.ui.actions.DartEditorActionDefinitionIds; |
| import com.google.dart.tools.ui.actions.DartdocActionGroup_OLD; |
| import com.google.dart.tools.ui.actions.OpenEditorActionGroup_NEW; |
| import com.google.dart.tools.ui.actions.OpenEditorActionGroup_OLD; |
| import com.google.dart.tools.ui.actions.OpenViewActionGroup_NEW; |
| import com.google.dart.tools.ui.actions.OpenViewActionGroup_OLD; |
| import com.google.dart.tools.ui.actions.RefactorActionGroup_NEW; |
| import com.google.dart.tools.ui.actions.ShowSelectionLabelAction; |
| import com.google.dart.tools.ui.instrumentation.UIInstrumentation; |
| import com.google.dart.tools.ui.instrumentation.UIInstrumentationBuilder; |
| import com.google.dart.tools.ui.internal.actions.ActionUtil; |
| import com.google.dart.tools.ui.internal.actions.FoldingActionGroup; |
| import com.google.dart.tools.ui.internal.formatter.DartFormatter; |
| import com.google.dart.tools.ui.internal.formatter.DartFormatter.FormattedSource; |
| import com.google.dart.tools.ui.internal.text.DartHelpContextIds; |
| import com.google.dart.tools.ui.internal.text.IProductConstants; |
| import com.google.dart.tools.ui.internal.text.ProductProperties; |
| import com.google.dart.tools.ui.internal.text.dart.DartPriorityFileEditor; |
| import com.google.dart.tools.ui.internal.text.dart.DartReconcilingEditor; |
| import com.google.dart.tools.ui.internal.text.dart.DartReconcilingStrategy; |
| import com.google.dart.tools.ui.internal.text.dart.hover.SourceViewerInformationControl; |
| import com.google.dart.tools.ui.internal.text.editor.saveactions.RemoveTrailingWhitespaceAction; |
| import com.google.dart.tools.ui.internal.text.editor.selectionactions.GoToNextPreviousMemberAction; |
| import com.google.dart.tools.ui.internal.text.editor.selectionactions.SelectionHistory; |
| import com.google.dart.tools.ui.internal.text.editor.selectionactions.StructureSelectEnclosingAction; |
| import com.google.dart.tools.ui.internal.text.editor.selectionactions.StructureSelectHistoryAction; |
| import com.google.dart.tools.ui.internal.text.editor.selectionactions.StructureSelectNextAction; |
| import com.google.dart.tools.ui.internal.text.editor.selectionactions.StructureSelectPreviousAction; |
| import com.google.dart.tools.ui.internal.text.editor.selectionactions.StructureSelectionAction; |
| import com.google.dart.tools.ui.internal.text.functions.DartChangeHover; |
| import com.google.dart.tools.ui.internal.text.functions.DartPairMatcher; |
| import com.google.dart.tools.ui.internal.text.functions.DartWordIterator; |
| import com.google.dart.tools.ui.internal.text.functions.DocumentCharacterIterator; |
| import com.google.dart.tools.ui.internal.text.functions.PreferencesAdapter; |
| import com.google.dart.tools.ui.internal.util.DartUIHelp; |
| import com.google.dart.tools.ui.internal.viewsupport.IViewPartInputProvider; |
| import com.google.dart.tools.ui.text.DartPartitions; |
| import com.google.dart.tools.ui.text.DartSourceViewerConfiguration; |
| import com.google.dart.tools.ui.text.DartTextTools; |
| import com.google.dart.tools.ui.text.folding.IDartFoldingStructureProvider; |
| import com.google.dart.tools.ui.text.folding.IDartFoldingStructureProviderExtension; |
| |
| import com.ibm.icu.text.BreakIterator; |
| |
| import org.eclipse.core.commands.operations.IOperationApprover; |
| import org.eclipse.core.commands.operations.IUndoContext; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ProjectScope; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.ListenerList; |
| 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.help.IContextProvider; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.text.BadLocationException; |
| 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.ITextOperationTarget; |
| import org.eclipse.jface.text.ITextSelection; |
| import org.eclipse.jface.text.ITextViewer; |
| import org.eclipse.jface.text.ITextViewerExtension2; |
| import org.eclipse.jface.text.ITextViewerExtension5; |
| import org.eclipse.jface.text.MarkSelection; |
| import org.eclipse.jface.text.Position; |
| import org.eclipse.jface.text.Region; |
| import org.eclipse.jface.text.TextSelection; |
| import org.eclipse.jface.text.TextUtilities; |
| import org.eclipse.jface.text.link.LinkedModeModel; |
| import org.eclipse.jface.text.link.LinkedPosition; |
| import org.eclipse.jface.text.reconciler.IReconciler; |
| import org.eclipse.jface.text.source.Annotation; |
| import org.eclipse.jface.text.source.CompositeRuler; |
| import org.eclipse.jface.text.source.IAnnotationModel; |
| import org.eclipse.jface.text.source.ICharacterPairMatcher; |
| import org.eclipse.jface.text.source.IOverviewRuler; |
| import org.eclipse.jface.text.source.ISourceViewer; |
| import org.eclipse.jface.text.source.IVerticalRuler; |
| import org.eclipse.jface.text.source.IVerticalRulerColumn; |
| import org.eclipse.jface.text.source.LineChangeHover; |
| import org.eclipse.jface.text.source.SourceViewerConfiguration; |
| import org.eclipse.jface.text.source.projection.ProjectionSupport; |
| import org.eclipse.jface.text.source.projection.ProjectionViewer; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| 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.ISelectionProvider; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.CaretEvent; |
| import org.eclipse.swt.custom.CaretListener; |
| import org.eclipse.swt.custom.ST; |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IFileEditorInput; |
| import org.eclipse.ui.IPageLayout; |
| import org.eclipse.ui.IPartListener2; |
| import org.eclipse.ui.IPartService; |
| import org.eclipse.ui.IURIEditorInput; |
| import org.eclipse.ui.IWorkbenchActionConstants; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchPart; |
| import org.eclipse.ui.IWorkbenchPartReference; |
| import org.eclipse.ui.IWorkbenchPartSite; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.actions.ActionContext; |
| import org.eclipse.ui.actions.ActionGroup; |
| import org.eclipse.ui.editors.text.DefaultEncodingSupport; |
| import org.eclipse.ui.editors.text.EditorsUI; |
| import org.eclipse.ui.editors.text.IEncodingSupport; |
| import org.eclipse.ui.operations.NonLocalUndoUserApprover; |
| import org.eclipse.ui.part.IShowInSource; |
| import org.eclipse.ui.part.IShowInTargetList; |
| import org.eclipse.ui.part.ShowInContext; |
| import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor; |
| import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; |
| import org.eclipse.ui.texteditor.AnnotationPreference; |
| import org.eclipse.ui.texteditor.ChainedPreferenceStore; |
| import org.eclipse.ui.texteditor.IEditorStatusLine; |
| import org.eclipse.ui.texteditor.ITextEditorActionConstants; |
| import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; |
| import org.eclipse.ui.texteditor.IUpdate; |
| import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; |
| import org.eclipse.ui.texteditor.TextNavigationAction; |
| import org.eclipse.ui.texteditor.TextOperationAction; |
| import org.eclipse.ui.views.contentoutline.ContentOutline; |
| import org.eclipse.ui.views.contentoutline.IContentOutlinePage; |
| import org.osgi.service.prefs.BackingStoreException; |
| |
| import java.io.File; |
| import java.lang.reflect.InvocationTargetException; |
| import java.net.URI; |
| import java.text.CharacterIterator; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * Dart specific text editor. |
| */ |
| @SuppressWarnings({"unused", "deprecation"}) |
| public abstract class DartEditor extends AbstractDecoratedTextEditor implements |
| IViewPartInputProvider, DartReconcilingEditor, DartPriorityFileEditor { |
| |
| /** |
| * Adapts an options {@link IEclipsePreferences} to |
| * {@link org.eclipse.jface.preference.IPreferenceStore}. |
| * <p> |
| * This preference store is read-only i.e. write access throws an |
| * {@link java.lang.UnsupportedOperationException}. |
| * </p> |
| */ |
| public static class EclipsePreferencesAdapter implements IPreferenceStore { |
| |
| /** |
| * Preference change listener. Listens for events preferences fires a |
| * {@link org.eclipse.jface.util.PropertyChangeEvent} on this adapter with arguments from the |
| * received event. |
| */ |
| private class PreferenceChangeListener implements IEclipsePreferences.IPreferenceChangeListener { |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void preferenceChange(final IEclipsePreferences.PreferenceChangeEvent event) { |
| if (Display.getCurrent() == null) { |
| Display.getDefault().asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| firePropertyChangeEvent(event.getKey(), event.getOldValue(), event.getNewValue()); |
| } |
| }); |
| } else { |
| firePropertyChangeEvent(event.getKey(), event.getOldValue(), event.getNewValue()); |
| } |
| } |
| } |
| |
| /** Listeners on on this adapter */ |
| private final ListenerList fListeners = new ListenerList(ListenerList.IDENTITY); |
| |
| /** Listener on the node */ |
| private final IEclipsePreferences.IPreferenceChangeListener fListener = new PreferenceChangeListener(); |
| |
| /** wrapped node */ |
| private final IScopeContext fContext; |
| private final String fQualifier; |
| |
| /** |
| * Initialize with the node to wrap |
| * |
| * @param context the context to access |
| * @param qualifier the qualifier |
| */ |
| public EclipsePreferencesAdapter(IScopeContext context, String qualifier) { |
| fContext = context; |
| fQualifier = qualifier; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void addPropertyChangeListener(IPropertyChangeListener listener) { |
| if (fListeners.size() == 0) { |
| getNode().addPreferenceChangeListener(fListener); |
| } |
| fListeners.add(listener); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public boolean contains(String name) { |
| return getNode().get(name, null) != null; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void firePropertyChangeEvent(String name, Object oldValue, Object newValue) { |
| PropertyChangeEvent event = new PropertyChangeEvent(this, name, oldValue, newValue); |
| Object[] listeners = fListeners.getListeners(); |
| for (int i = 0; i < listeners.length; i++) { |
| ((IPropertyChangeListener) listeners[i]).propertyChange(event); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public boolean getBoolean(String name) { |
| return getNode().getBoolean(name, BOOLEAN_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public boolean getDefaultBoolean(String name) { |
| return BOOLEAN_DEFAULT_DEFAULT; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public double getDefaultDouble(String name) { |
| return DOUBLE_DEFAULT_DEFAULT; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public float getDefaultFloat(String name) { |
| return FLOAT_DEFAULT_DEFAULT; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public int getDefaultInt(String name) { |
| return INT_DEFAULT_DEFAULT; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public long getDefaultLong(String name) { |
| return LONG_DEFAULT_DEFAULT; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public String getDefaultString(String name) { |
| return STRING_DEFAULT_DEFAULT; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public double getDouble(String name) { |
| return getNode().getDouble(name, DOUBLE_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public float getFloat(String name) { |
| return getNode().getFloat(name, FLOAT_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public int getInt(String name) { |
| return getNode().getInt(name, INT_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public long getLong(String name) { |
| return getNode().getLong(name, LONG_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public String getString(String name) { |
| return getNode().get(name, STRING_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public boolean isDefault(String name) { |
| return false; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public boolean needsSaving() { |
| try { |
| return getNode().keys().length > 0; |
| } catch (BackingStoreException e) { |
| // ignore |
| } |
| return true; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void putValue(String name, String value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void removePropertyChangeListener(IPropertyChangeListener listener) { |
| fListeners.remove(listener); |
| if (fListeners.size() == 0) { |
| getNode().removePreferenceChangeListener(fListener); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setDefault(String name, boolean value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setDefault(String name, double value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setDefault(String name, float value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setDefault(String name, int value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setDefault(String name, long value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setDefault(String name, String defaultObject) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setToDefault(String name) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setValue(String name, boolean value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setValue(String name, double value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setValue(String name, float value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setValue(String name, int value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setValue(String name, long value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setValue(String name, String value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| protected IEclipsePreferences getNode() { |
| return fContext.getNode(fQualifier); |
| } |
| |
| } |
| |
| /** |
| * Internal implementation class for a change listener. |
| */ |
| protected abstract class AbstractSelectionChangedListener implements ISelectionChangedListener { |
| |
| /** |
| * Installs this selection changed listener with the given selection provider. If the selection |
| * provider is a post selection provider, post selection changed events are the preferred |
| * choice, otherwise normal selection changed events are requested. |
| * |
| * @param selectionProvider |
| */ |
| public void install(ISelectionProvider selectionProvider) { |
| if (selectionProvider == null) { |
| return; |
| } |
| |
| if (selectionProvider instanceof IPostSelectionProvider) { |
| IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider; |
| provider.addPostSelectionChangedListener(this); |
| } else { |
| selectionProvider.addSelectionChangedListener(this); |
| } |
| } |
| |
| /** |
| * Removes this selection changed listener from the given selection provider. |
| * |
| * @param selectionProvider the selection provider |
| */ |
| public void uninstall(ISelectionProvider selectionProvider) { |
| if (selectionProvider == null) { |
| return; |
| } |
| |
| if (selectionProvider instanceof IPostSelectionProvider) { |
| IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider; |
| provider.removePostSelectionChangedListener(this); |
| } else { |
| selectionProvider.removeSelectionChangedListener(this); |
| } |
| } |
| } |
| |
| /** |
| * Text operation action to delete the next sub-word. |
| */ |
| protected class DeleteNextSubWordAction extends NextSubWordAction implements IUpdate { |
| |
| /** |
| * Creates a new delete next sub-word action. |
| */ |
| public DeleteNextSubWordAction() { |
| super(ST.DELETE_WORD_NEXT); |
| } |
| |
| @Override |
| public void update() { |
| setEnabled(isEditorInputModifiable()); |
| } |
| |
| @Override |
| protected void setCaretPosition(final int position) { |
| if (!validateEditorInputState()) { |
| return; |
| } |
| |
| final ISourceViewer viewer = getSourceViewer(); |
| StyledText text = viewer.getTextWidget(); |
| Point widgetSelection = text.getSelection(); |
| if (isBlockSelectionModeEnabled() && widgetSelection.y != widgetSelection.x) { |
| final int caret = text.getCaretOffset(); |
| final int offset = modelOffset2WidgetOffset(viewer, position); |
| |
| if (caret == widgetSelection.x) { |
| text.setSelectionRange(widgetSelection.y, offset - widgetSelection.y); |
| } else { |
| text.setSelectionRange(widgetSelection.x, offset - widgetSelection.x); |
| } |
| text.invokeAction(ST.DELETE_NEXT); |
| } else { |
| Point selection = viewer.getSelectedRange(); |
| final int caret, length; |
| if (selection.y != 0) { |
| caret = selection.x; |
| length = selection.y; |
| } else { |
| caret = widgetOffset2ModelOffset(viewer, text.getCaretOffset()); |
| length = position - caret; |
| } |
| |
| try { |
| viewer.getDocument().replace(caret, length, ""); //$NON-NLS-1$ |
| } catch (BadLocationException exception) { |
| // Should not happen |
| } |
| } |
| } |
| } |
| |
| /** |
| * Text operation action to delete the previous sub-word. |
| */ |
| protected class DeletePreviousSubWordAction extends PreviousSubWordAction implements IUpdate { |
| |
| /** |
| * Creates a new delete previous sub-word action. |
| */ |
| public DeletePreviousSubWordAction() { |
| super(ST.DELETE_WORD_PREVIOUS); |
| } |
| |
| @Override |
| public void update() { |
| setEnabled(isEditorInputModifiable()); |
| } |
| |
| @Override |
| protected void setCaretPosition(int position) { |
| if (!validateEditorInputState()) { |
| return; |
| } |
| |
| final int length; |
| final ISourceViewer viewer = getSourceViewer(); |
| StyledText text = viewer.getTextWidget(); |
| Point widgetSelection = text.getSelection(); |
| if (isBlockSelectionModeEnabled() && widgetSelection.y != widgetSelection.x) { |
| final int caret = text.getCaretOffset(); |
| final int offset = modelOffset2WidgetOffset(viewer, position); |
| |
| if (caret == widgetSelection.x) { |
| text.setSelectionRange(widgetSelection.y, offset - widgetSelection.y); |
| } else { |
| text.setSelectionRange(widgetSelection.x, offset - widgetSelection.x); |
| } |
| text.invokeAction(ST.DELETE_PREVIOUS); |
| } else { |
| Point selection = viewer.getSelectedRange(); |
| if (selection.y != 0) { |
| position = selection.x; |
| length = selection.y; |
| } else { |
| length = widgetOffset2ModelOffset(viewer, text.getCaretOffset()) - position; |
| } |
| |
| try { |
| viewer.getDocument().replace(position, length, ""); //$NON-NLS-1$ |
| } catch (BadLocationException exception) { |
| // Should not happen |
| } |
| } |
| } |
| } |
| |
| /** |
| * Format element action to format the enclosing Dart element. |
| * <p> |
| * The format element action works as follows: |
| * <ul> |
| * <li>If there is no selection and the caret is positioned on a Dart element, only this element |
| * is formatted. If the element has some accompanying comment, then the comment is formatted as |
| * well.</li> |
| * <li>If the selection spans one or more partitions of the document, then all partitions covered |
| * by the selection are entirely formatted.</li> |
| * <p> |
| * Partitions at the end of the selection are not completed, except for comments. |
| */ |
| protected class FormatElementAction extends Action implements IUpdate { |
| |
| private class FormatElementJob extends Job { |
| |
| // For debugging. |
| private final boolean PRINT_TO_CONSOLE = false; |
| |
| private final IFile file; |
| |
| FormatElementJob(IFile file) { |
| super("Formatting " + file.getLocation()); |
| this.file = file; |
| } |
| |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| |
| MessageConsole console = DartCore.getConsole(); |
| |
| if (PRINT_TO_CONSOLE) { |
| console.clear(); |
| console.println("Formatting " + file.getName() + " ..."); |
| } |
| |
| final ISourceViewer sourceViewer = getSourceViewer(); |
| final IDocument document = sourceViewer.getDocument(); |
| |
| try { |
| |
| final Point initialSelection = new Point(-1, 0); |
| Display.getDefault().syncExec(new Runnable() { |
| @Override |
| public void run() { |
| Point selection = sourceViewer.getSelectedRange(); |
| initialSelection.x = selection.x; |
| initialSelection.y = selection.y; |
| } |
| }); |
| |
| final String unformattedSource = document.get(); |
| |
| final FormattedSource formatResult = DartFormatter.format( |
| unformattedSource, |
| initialSelection, |
| monitor); |
| |
| Display.getDefault().syncExec(new Runnable() { |
| @Override |
| public void run() { |
| if (!formatResult.source.equals(unformattedSource)) { |
| try { |
| document.replace( |
| formatResult.changeOffset, |
| formatResult.changeLength, |
| formatResult.changeReplacement); |
| sourceViewer.revealRange( |
| formatResult.selectionOffset, |
| formatResult.selectionLength); |
| sourceViewer.setSelectedRange( |
| formatResult.selectionOffset, |
| formatResult.selectionLength); |
| } catch (BadLocationException e) { |
| DartToolsPlugin.log(e); |
| } |
| } |
| } |
| }); |
| } catch (Exception e) { |
| |
| String msg = null; |
| |
| if (isParseFailure(e)) { |
| msg = "fix parse errors and try again."; |
| } else { |
| msg = e.getMessage(); |
| DartToolsPlugin.log(e); |
| } |
| |
| if (PRINT_TO_CONSOLE) { |
| console.clear(); |
| console.println("Unable to format " + file.getName() + ": " + msg); |
| } else { |
| showMessage("Unable to format " + file.getName() + ": " + msg); |
| } |
| |
| return Status.CANCEL_STATUS; |
| } |
| |
| if (PRINT_TO_CONSOLE) { |
| console.clear(); |
| } |
| |
| return Status.OK_STATUS; |
| } |
| |
| private boolean isParseFailure(Exception e) { |
| String message = e.getMessage(); |
| //TODO (pquitslund): use a return code or something better to signal parse failures |
| return message != null |
| && message.startsWith("Could not format because the source could not be parsed:"); |
| } |
| }; |
| |
| FormatElementAction() { |
| setEnabled(isEditorInputModifiable()); |
| setText("Format"); |
| } |
| |
| @Override |
| public boolean isEnabled() { |
| return super.isEnabled() && DartFormatter.isAvailable(); |
| } |
| |
| @Override |
| public void run() { |
| IFile file = getInputResourceFile(); |
| new FormatElementJob(file).schedule(); |
| } |
| |
| @Override |
| public void update() { |
| setEnabled(isEditorInputModifiable()); |
| } |
| |
| private void showMessage(final String msg) { |
| final Display display = getSite().getShell().getDisplay(); |
| display.syncExec(new Runnable() { |
| @Override |
| public void run() { |
| IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class); |
| if (statusLine != null) { |
| statusLine.setMessage(true, msg, null); |
| } |
| display.beep(); |
| } |
| }); |
| } |
| |
| } |
| |
| /** |
| * Text navigation action to navigate to the next sub-word. |
| */ |
| protected class NavigateNextSubWordAction extends NextSubWordAction { |
| |
| /** |
| * Creates a new navigate next sub-word action. |
| */ |
| public NavigateNextSubWordAction() { |
| super(ST.WORD_NEXT); |
| } |
| |
| @Override |
| protected void setCaretPosition(final int position) { |
| getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position)); |
| } |
| } |
| |
| /** |
| * Text navigation action to navigate to the previous sub-word. |
| */ |
| protected class NavigatePreviousSubWordAction extends PreviousSubWordAction { |
| |
| /** |
| * Creates a new navigate previous sub-word action. |
| */ |
| public NavigatePreviousSubWordAction() { |
| super(ST.WORD_PREVIOUS); |
| } |
| |
| @Override |
| protected void setCaretPosition(final int position) { |
| getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position)); |
| } |
| } |
| |
| /** |
| * Text navigation action to navigate to the next sub-word. |
| */ |
| protected abstract class NextSubWordAction extends TextNavigationAction { |
| |
| protected DartWordIterator fIterator = new DartWordIterator(); |
| |
| /** |
| * Creates a new next sub-word action. |
| * |
| * @param code Action code for the default operation. Must be an action code from @see |
| * org.eclipse.swt.custom.ST. |
| */ |
| protected NextSubWordAction(int code) { |
| super(getSourceViewer().getTextWidget(), code); |
| } |
| |
| @Override |
| public void run() { |
| // Check whether we are in a Dart code partition and the preference is enabled |
| final IPreferenceStore store = getPreferenceStore(); |
| if (!store.getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) { |
| super.run(); |
| return; |
| } |
| |
| final ISourceViewer viewer = getSourceViewer(); |
| final IDocument document = viewer.getDocument(); |
| fIterator.setText((CharacterIterator) new DocumentCharacterIterator(document)); |
| int position = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset()); |
| if (position == -1) { |
| return; |
| } |
| |
| int next = findNextPosition(position); |
| try { |
| if (isBlockSelectionModeEnabled() |
| && document.getLineOfOffset(next) != document.getLineOfOffset(position)) { |
| super.run(); // may navigate into virtual white space |
| } else if (next != BreakIterator.DONE) { |
| setCaretPosition(next); |
| getTextWidget().showSelection(); |
| fireSelectionChanged(); |
| } |
| } catch (BadLocationException x) { |
| // ignore |
| } |
| } |
| |
| /** |
| * Finds the next position after the given position. |
| * |
| * @param position the current position |
| * @return the next position |
| */ |
| protected int findNextPosition(int position) { |
| ISourceViewer viewer = getSourceViewer(); |
| int widget = -1; |
| int next = position; |
| while (next != BreakIterator.DONE && widget == -1) { // TODO: optimize |
| next = fIterator.following(next); |
| if (next != BreakIterator.DONE) { |
| widget = modelOffset2WidgetOffset(viewer, next); |
| } |
| } |
| |
| IDocument document = viewer.getDocument(); |
| LinkedModeModel model = LinkedModeModel.getModel(document, position); |
| if (model != null) { |
| LinkedPosition linkedPosition = model.findPosition(new LinkedPosition(document, position, 0)); |
| if (linkedPosition != null) { |
| int linkedPositionEnd = linkedPosition.getOffset() + linkedPosition.getLength(); |
| if (position != linkedPositionEnd && linkedPositionEnd < next) { |
| next = linkedPositionEnd; |
| } |
| } else { |
| LinkedPosition nextLinkedPosition = model.findPosition(new LinkedPosition( |
| document, |
| next, |
| 0)); |
| if (nextLinkedPosition != null) { |
| int nextLinkedPositionOffset = nextLinkedPosition.getOffset(); |
| if (position != nextLinkedPositionOffset && nextLinkedPositionOffset < next) { |
| next = nextLinkedPositionOffset; |
| } |
| } |
| } |
| } |
| |
| return next; |
| } |
| |
| /** |
| * Sets the caret position to the sub-word boundary given with <code>position</code>. |
| * |
| * @param position Position where the action should move the caret |
| */ |
| protected abstract void setCaretPosition(int position); |
| } |
| |
| /** |
| * Text navigation action to navigate to the previous sub-word. |
| */ |
| protected abstract class PreviousSubWordAction extends TextNavigationAction { |
| |
| protected DartWordIterator fIterator = new DartWordIterator(); |
| |
| /** |
| * Creates a new previous sub-word action. |
| * |
| * @param code Action code for the default operation. Must be an action code from @see |
| * org.eclipse.swt.custom.ST. |
| */ |
| protected PreviousSubWordAction(final int code) { |
| super(getSourceViewer().getTextWidget(), code); |
| } |
| |
| @Override |
| public void run() { |
| // Check whether we are in a Dart code partition and the preference is enabled |
| final IPreferenceStore store = getPreferenceStore(); |
| if (!store.getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) { |
| super.run(); |
| return; |
| } |
| |
| final ISourceViewer viewer = getSourceViewer(); |
| final IDocument document = viewer.getDocument(); |
| fIterator.setText((CharacterIterator) new DocumentCharacterIterator(document)); |
| int position = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset()); |
| if (position == -1) { |
| return; |
| } |
| |
| int previous = findPreviousPosition(position); |
| try { |
| if (isBlockSelectionModeEnabled() |
| && document.getLineOfOffset(previous) != document.getLineOfOffset(position)) { |
| super.run(); // may navigate into virtual white space |
| } else if (previous != BreakIterator.DONE) { |
| setCaretPosition(previous); |
| getTextWidget().showSelection(); |
| fireSelectionChanged(); |
| } |
| } catch (BadLocationException x) { |
| // ignore - getLineOfOffset failed |
| } |
| |
| } |
| |
| /** |
| * Finds the previous position before the given position. |
| * |
| * @param position the current position |
| * @return the previous position |
| */ |
| protected int findPreviousPosition(int position) { |
| ISourceViewer viewer = getSourceViewer(); |
| int widget = -1; |
| int previous = position; |
| while (previous != BreakIterator.DONE && widget == -1) { // TODO: optimize |
| previous = fIterator.preceding(previous); |
| if (previous != BreakIterator.DONE) { |
| widget = modelOffset2WidgetOffset(viewer, previous); |
| } |
| } |
| |
| IDocument document = viewer.getDocument(); |
| LinkedModeModel model = LinkedModeModel.getModel(document, position); |
| if (model != null) { |
| LinkedPosition linkedPosition = model.findPosition(new LinkedPosition(document, position, 0)); |
| if (linkedPosition != null) { |
| int linkedPositionOffset = linkedPosition.getOffset(); |
| if (position != linkedPositionOffset && previous < linkedPositionOffset) { |
| previous = linkedPositionOffset; |
| } |
| } else { |
| LinkedPosition previousLinkedPosition = model.findPosition(new LinkedPosition( |
| document, |
| previous, |
| 0)); |
| if (previousLinkedPosition != null) { |
| int previousLinkedPositionEnd = previousLinkedPosition.getOffset() |
| + previousLinkedPosition.getLength(); |
| if (position != previousLinkedPositionEnd && previous < previousLinkedPositionEnd) { |
| previous = previousLinkedPositionEnd; |
| } |
| } |
| } |
| } |
| |
| return previous; |
| } |
| |
| /** |
| * Sets the caret position to the sub-word boundary given with <code>position</code>. |
| * |
| * @param position Position where the action should move the caret |
| */ |
| protected abstract void setCaretPosition(int position); |
| } |
| |
| /** |
| * Text operation action to select the next sub-word. |
| */ |
| protected class SelectNextSubWordAction extends NextSubWordAction { |
| |
| /** |
| * Creates a new select next sub-word action. |
| */ |
| public SelectNextSubWordAction() { |
| super(ST.SELECT_WORD_NEXT); |
| } |
| |
| @Override |
| protected void setCaretPosition(final int position) { |
| final ISourceViewer viewer = getSourceViewer(); |
| |
| final StyledText text = viewer.getTextWidget(); |
| if (text != null && !text.isDisposed()) { |
| |
| final Point selection = text.getSelection(); |
| final int caret = text.getCaretOffset(); |
| final int offset = modelOffset2WidgetOffset(viewer, position); |
| |
| if (caret == selection.x) { |
| text.setSelectionRange(selection.y, offset - selection.y); |
| } else { |
| text.setSelectionRange(selection.x, offset - selection.x); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Text operation action to select the previous sub-word. |
| */ |
| protected class SelectPreviousSubWordAction extends PreviousSubWordAction { |
| |
| /** |
| * Creates a new select previous sub-word action. |
| */ |
| public SelectPreviousSubWordAction() { |
| super(ST.SELECT_WORD_PREVIOUS); |
| } |
| |
| @Override |
| protected void setCaretPosition(final int position) { |
| final ISourceViewer viewer = getSourceViewer(); |
| |
| final StyledText text = viewer.getTextWidget(); |
| if (text != null && !text.isDisposed()) { |
| |
| final Point selection = text.getSelection(); |
| final int caret = text.getCaretOffset(); |
| final int offset = modelOffset2WidgetOffset(viewer, position); |
| |
| if (caret == selection.x) { |
| text.setSelectionRange(selection.y, offset - selection.y); |
| } else { |
| text.setSelectionRange(selection.x, offset - selection.x); |
| } |
| } |
| } |
| } |
| |
| /** |
| * This action implements smart home. Instead of going to the start of a line it does the |
| * following: - 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. - if the caret is before the line's first non-whitespace the caret is |
| * moved to the beginning of the line - if the caret is at the beginning of the line see first |
| * case. |
| */ |
| protected class SmartLineStartAction extends LineStartAction { |
| |
| /** |
| * Creates a new smart line start action |
| * |
| * @param textWidget the styled text widget |
| * @param doSelect a boolean flag which tells if the text up to the beginning of the line should |
| * be selected |
| */ |
| public SmartLineStartAction(final StyledText textWidget, final boolean doSelect) { |
| super(textWidget, doSelect); |
| } |
| |
| @Override |
| protected int getLineStartPosition(final IDocument document, final String line, |
| final int length, final int offset) { |
| |
| String type = IDocument.DEFAULT_CONTENT_TYPE; |
| try { |
| type = TextUtilities.getContentType( |
| document, |
| DartPartitions.DART_PARTITIONING, |
| offset, |
| true); |
| } catch (BadLocationException exception) { |
| // Should not happen |
| } |
| |
| int index = super.getLineStartPosition(document, line, length, offset); |
| if (type.equals(DartPartitions.DART_DOC) |
| || type.equals(DartPartitions.DART_MULTI_LINE_COMMENT)) { |
| if (index < length - 1 && line.charAt(index) == '*' && line.charAt(index + 1) != '/') { |
| do { |
| ++index; |
| } while (index < length && Character.isWhitespace(line.charAt(index))); |
| } |
| } else { |
| if (index < length - 1 && line.charAt(index) == '/' && line.charAt(index + 1) == '/') { |
| if (type.equals(DartPartitions.DART_SINGLE_LINE_DOC) |
| && (index < length - 2 && line.charAt(index + 2) == '/')) { |
| index++; |
| } |
| index++; |
| do { |
| ++index; |
| } while (index < length && Character.isWhitespace(line.charAt(index))); |
| } |
| } |
| return index; |
| } |
| } |
| |
| private class DartSelectionProvider extends SelectionProvider { |
| private final Map<ISelectionChangedListener, ISelectionChangedListener> listeners = Maps.newHashMap(); |
| |
| @Override |
| public void addPostSelectionChangedListener(ISelectionChangedListener listener) { |
| ISelectionChangedListener dartListener = newDartSelectionListener(listener); |
| super.addPostSelectionChangedListener(dartListener); |
| } |
| |
| @Override |
| public void addSelectionChangedListener(ISelectionChangedListener listener) { |
| ISelectionChangedListener dartListener = newDartSelectionListener(listener); |
| super.addSelectionChangedListener(dartListener); |
| } |
| |
| @Override |
| public ISelection getSelection() { |
| ISelection selection = super.getSelection(); |
| return newDartSelection(selection); |
| } |
| |
| @Override |
| public void removePostSelectionChangedListener(ISelectionChangedListener listener) { |
| ISelectionChangedListener dartListener = listeners.remove(listener); |
| if (dartListener != null) { |
| super.removePostSelectionChangedListener(dartListener); |
| } |
| } |
| |
| @Override |
| public void removeSelectionChangedListener(ISelectionChangedListener listener) { |
| ISelectionChangedListener dartListener = listeners.remove(listener); |
| if (dartListener != null) { |
| super.removeSelectionChangedListener(dartListener); |
| } |
| } |
| |
| private ISelection newDartSelection(ISelection selection) { |
| if (selection == null) { |
| return new DartSelection(DartEditor.this, null, -1, 0); |
| } |
| if (selection instanceof MarkSelection) { |
| MarkSelection sel = (MarkSelection) selection; |
| IDocument doc = sel.getDocument(); |
| return new DartSelection(DartEditor.this, doc, sel.getOffset(), sel.getLength()); |
| } |
| ITextSelection textSelection = (ITextSelection) selection; |
| // prepare document |
| ISourceViewer sourceViewer = getSourceViewer(); |
| if (sourceViewer == null) { |
| return new DartSelection(DartEditor.this, null, -1, 0); |
| } |
| IDocument document = sourceViewer.getDocument(); |
| // prepare AssistContext |
| AssistContext assistContext = getAssistContext(textSelection); |
| // OK, wrap into DartSelection |
| return new DartSelection( |
| DartEditor.this, |
| document, |
| textSelection.getOffset(), |
| textSelection.getLength()); |
| } |
| |
| private ISelectionChangedListener newDartSelectionListener( |
| final ISelectionChangedListener listener) { |
| ISelectionChangedListener dartListener = new ISelectionChangedListener() { |
| @Override |
| public void selectionChanged(SelectionChangedEvent event) { |
| listener.selectionChanged(new SelectionChangedEvent( |
| event.getSelectionProvider(), |
| newDartSelection(event.getSelection()))); |
| } |
| }; |
| listeners.put(listener, dartListener); |
| return dartListener; |
| } |
| } |
| |
| /** |
| * Updates the outline page selection and this editor's range indicator. |
| */ |
| private class EditorSelectionChangedListener extends AbstractSelectionChangedListener { |
| |
| @Override |
| public void selectionChanged(SelectionChangedEvent event) { |
| // XXX: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=56161 |
| DartEditor.this.selectionChanged(); |
| } |
| } |
| |
| /** |
| * An adapter from new to old source reference abstractions. |
| */ |
| private static final class SourceReferenceAdapter implements SourceReference { |
| |
| private final SourceRange sourceRange; |
| |
| private SourceReferenceAdapter(com.google.dart.engine.element.Element element) { |
| sourceRange = new SourceRange(element.getNameOffset(), element.getDisplayName().length()); |
| } |
| |
| @Override |
| public boolean exists() { |
| // Unused in this context |
| return true; |
| } |
| |
| @Override |
| public SourceRange getNameRange() throws DartModelException { |
| return sourceRange; |
| } |
| |
| @Override |
| public String getSource() throws DartModelException { |
| // Unused in this context |
| return ""; |
| } |
| |
| @Override |
| public SourceRange getSourceRange() throws DartModelException { |
| // Unused in this context |
| return sourceRange; |
| } |
| |
| } |
| |
| /** |
| * Runner that will toggle folding either instantly (if the editor is visible) or the next time it |
| * becomes visible. If a runner is started when there is already one registered, the registered |
| * one is canceled as toggling folding twice is a no-op. |
| * <p> |
| * The access to the fFoldingRunner field is not thread-safe, it is assumed that |
| * <code>runWhenNextVisible</code> is only called from the UI thread. |
| * </p> |
| */ |
| private final class ToggleFoldingRunner implements IPartListener2 { |
| /** |
| * The workbench page we registered the part listener with, or <code>null</code>. |
| */ |
| private IWorkbenchPage fPage; |
| |
| @Override |
| public void partActivated(IWorkbenchPartReference partRef) { |
| } |
| |
| @Override |
| public void partBroughtToTop(IWorkbenchPartReference partRef) { |
| } |
| |
| @Override |
| public void partClosed(IWorkbenchPartReference partRef) { |
| if (DartEditor.this.equals(partRef.getPart(false))) { |
| cancel(); |
| } |
| } |
| |
| @Override |
| public void partDeactivated(IWorkbenchPartReference partRef) { |
| } |
| |
| @Override |
| public void partHidden(IWorkbenchPartReference partRef) { |
| } |
| |
| @Override |
| public void partInputChanged(IWorkbenchPartReference partRef) { |
| } |
| |
| @Override |
| public void partOpened(IWorkbenchPartReference partRef) { |
| } |
| |
| @Override |
| public void partVisible(IWorkbenchPartReference partRef) { |
| if (DartEditor.this.equals(partRef.getPart(false))) { |
| cancel(); |
| toggleFolding(); |
| } |
| } |
| |
| /** |
| * Makes sure that the editor's folding state is correct the next time it becomes visible. If it |
| * already is visible, it toggles the folding state. If not, it either registers a part listener |
| * to toggle folding when the editor becomes visible, or cancels an already registered runner. |
| */ |
| public void runWhenNextVisible() { |
| // if there is one already: toggling twice is the identity |
| if (fFoldingRunner != null) { |
| fFoldingRunner.cancel(); |
| return; |
| } |
| IWorkbenchPartSite site = getSite(); |
| if (site != null) { |
| IWorkbenchPage page = site.getPage(); |
| if (!page.isPartVisible(DartEditor.this)) { |
| // if we're not visible - defer until visible |
| fPage = page; |
| fFoldingRunner = this; |
| page.addPartListener(this); |
| return; |
| } |
| } |
| // we're visible - run now |
| toggleFolding(); |
| } |
| |
| /** |
| * Remove the listener and clear the field. |
| */ |
| private void cancel() { |
| if (fPage != null) { |
| fPage.removePartListener(this); |
| fPage = null; |
| } |
| if (fFoldingRunner == this) { |
| fFoldingRunner = null; |
| } |
| } |
| |
| /** |
| * Does the actual toggling of projection. |
| */ |
| private void toggleFolding() { |
| ISourceViewer sourceViewer = getSourceViewer(); |
| if (sourceViewer instanceof ProjectionViewer) { |
| ProjectionViewer pv = (ProjectionViewer) sourceViewer; |
| if (pv.isProjectionMode() != isFoldingEnabled()) { |
| if (pv.canDoOperation(ProjectionViewer.TOGGLE)) { |
| pv.doOperation(ProjectionViewer.TOGGLE); |
| } |
| } |
| } |
| } |
| } |
| |
| private static boolean isBracket(char character) { |
| for (int i = 0; i != BRACKETS.length; ++i) { |
| if (character == BRACKETS[i]) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private static boolean isSurroundedByBrackets(IDocument document, int offset) { |
| if (offset == 0 || offset == document.getLength()) { |
| return false; |
| } |
| |
| try { |
| return isBracket(document.getChar(offset - 1)) && isBracket(document.getChar(offset)); |
| |
| } catch (BadLocationException e) { |
| return false; |
| } |
| } |
| |
| private IFile inputResourceFile; |
| |
| private File inputJavaFile; |
| private volatile com.google.dart.engine.ast.CompilationUnit resolvedUnit; |
| private SourceRange textSelectionRange; |
| |
| /** Preference key for matching brackets */ |
| protected final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS; |
| |
| /** Preference key for matching brackets color */ |
| protected final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR; |
| |
| protected final static char[] BRACKETS = {'{', '}', '(', ')', '[', ']', '<', '>'}; |
| |
| /** The outline page */ |
| protected DartOutlinePage fOutlinePage_OLD; |
| |
| /** The outline page */ |
| protected DartOutlinePage_NEW fOutlinePage_NEW; |
| private Outline outline; |
| |
| private AnalysisServerNavigationListener navigationListener = new AnalysisServerNavigationListener() { |
| @Override |
| public void computedNavigation(String file, NavigationRegion[] regions) { |
| } |
| }; |
| |
| private Outline lastOutline; |
| private AnalysisServerOutlineListener outlineListener = new AnalysisServerOutlineListener() { |
| @Override |
| public void computedOutline(String file, final Outline outline) { |
| DartEditor.this.outline = outline; |
| Display.getDefault().asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| lastOutline = outline; |
| updateOutlinePageNew(outline); |
| } |
| }); |
| } |
| }; |
| |
| private SemanticHighlightingManager_NEW analysisServerHighlightManager; |
| |
| /** Outliner context menu Id */ |
| protected String fOutlinerContextMenuId; |
| /** |
| * The editor selection changed listener. |
| */ |
| private EditorSelectionChangedListener fEditorSelectionChangedListener; |
| /** The editor's bracket matcher */ |
| protected DartPairMatcher fBracketMatcher = new DartPairMatcher(BRACKETS); |
| |
| /** This editor's encoding support */ |
| private DefaultEncodingSupport fEncodingSupport; |
| |
| /** History for structure select action */ |
| private SelectionHistory fSelectionHistory; |
| protected CompositeActionGroup fActionGroups; |
| /** |
| * The action group for folding. |
| */ |
| private FoldingActionGroup fFoldingGroup; |
| private CompositeActionGroup fOpenEditorActionGroup; |
| |
| /** |
| * Removes trailing whitespace on editor saves. |
| */ |
| private RemoveTrailingWhitespaceAction removeTrailingWhitespaceAction; |
| |
| private MarkOccurrencesManager_OLD occurrencesManager_OLD; |
| private MarkOccurrencesManager_NEW occurrencesManager_NEW; |
| |
| /** |
| * This editor's projection support |
| */ |
| private ProjectionSupport fProjectionSupport; |
| /** |
| * This editor's projection model updater |
| */ |
| private IDartFoldingStructureProvider fProjectionModelUpdater; |
| |
| /** |
| * The override and implements indicator manager for this editor. |
| */ |
| protected OverrideIndicatorManager fOverrideIndicatorManager; |
| |
| /** |
| * Semantic highlighting manager |
| */ |
| protected SemanticHighlightingManager fSemanticManager; |
| |
| /** |
| * The folding runner. |
| */ |
| private ToggleFoldingRunner fFoldingRunner; |
| |
| /** |
| * Tells whether the selection changed event is caused by a call to |
| * {@link #gotoAnnotation(boolean)}. |
| */ |
| private boolean fSelectionChangedViaGotoAnnotation; |
| |
| /** |
| * The cached selected range. |
| * |
| * @see ITextViewer#getSelectedRange() |
| */ |
| private Point fCachedSelectedRange; |
| |
| private ShowSelectionLabelAction showSelectionLabel = new ShowSelectionLabelAction(); |
| |
| private SelectionProvider selectionProvider = new DartSelectionProvider(); |
| |
| private final List<ISelectionChangedListener> dartSelectionListeners = Lists.newArrayList(); |
| |
| private final CaretListener dartSelectionCaretListener = new CaretListener() { |
| private boolean caretMovedScheduled = false; |
| |
| @Override |
| public void caretMoved(CaretEvent event) { |
| // already scheduled and not executed yet |
| if (caretMovedScheduled) { |
| return; |
| } |
| caretMovedScheduled = true; |
| // schedule selection update |
| Display.getCurrent().asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| caretMovedScheduled = false; |
| if (isDisposed()) { |
| return; |
| } |
| applySelectionToOutline(); |
| fireDartSelectionListeners(); |
| } |
| }); |
| } |
| }; |
| //Patched to address dartbug.com/7998 |
| private ISelectionChangedListener patchedSelectionChangedListener; |
| |
| /** |
| * Default constructor. |
| */ |
| public DartEditor() { |
| super(); |
| } |
| |
| /** |
| * Specifies that given {@link ISelectionChangedListener} should be invoked on any |
| * {@link DartSelection} change - selection, {@link CompilationUnit}. |
| */ |
| public void addDartSelectionListener(ISelectionChangedListener listener) { |
| dartSelectionListeners.add(listener); |
| } |
| |
| @Override |
| public void applyResolvedUnit(com.google.dart.engine.ast.CompilationUnit unit) { |
| if (isDisposed()) { |
| return; |
| } |
| // ignore if already know that we don't have resolved unit |
| if (resolvedUnit == null && unit == null) { |
| return; |
| } |
| // ignore if this unit has already been set |
| if (resolvedUnit == unit) { |
| return; |
| } |
| // OK, schedule selection update |
| resolvedUnit = unit; |
| ExecutionUtils.runLogAsync(new RunnableEx() { |
| @Override |
| public void run() { |
| if (isDisposed()) { |
| return; |
| } |
| // update Outline |
| if (resolvedUnit != null && fOutlinePage_OLD != null) { |
| if (fOutlinePage_OLD != null) { |
| fOutlinePage_OLD.setInput(resolvedUnit); |
| } |
| applySelectionToOutline(); |
| } |
| // update selection listeners |
| fireDartSelectionListeners(); |
| } |
| }); |
| } |
| |
| /** |
| * Collapses all foldable comments if supported by the folding structure provider. |
| */ |
| public void collapseComments() { |
| DartX.todo("folding"); |
| if (fProjectionModelUpdater instanceof IDartFoldingStructureProviderExtension) { |
| IDartFoldingStructureProviderExtension extension = (IDartFoldingStructureProviderExtension) fProjectionModelUpdater; |
| extension.collapseComments(); |
| } |
| } |
| |
| /** |
| * Collapses all foldable members if supported by the folding structure provider. |
| */ |
| public void collapseMembers() { |
| DartX.todo("folding"); |
| if (fProjectionModelUpdater instanceof IDartFoldingStructureProviderExtension) { |
| IDartFoldingStructureProviderExtension extension = (IDartFoldingStructureProviderExtension) fProjectionModelUpdater; |
| extension.collapseMembers(); |
| } |
| } |
| |
| public ISelection createElementSelection() { |
| ITextSelection textSelection = (ITextSelection) getSelectionProvider().getSelection(); |
| IDocument document = getSourceViewer().getDocument(); |
| return textSelection; |
| } |
| |
| @Override |
| public void createPartControl(Composite parent) { |
| super.createPartControl(parent); |
| patchSelectionChangeParticipation(); |
| getSourceViewer().getTextWidget().addCaretListener(dartSelectionCaretListener); |
| |
| // Set tab width |
| IPreferenceStore store = getPreferenceStore(); |
| if (store != null) { |
| int tabWidth = store.getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH); |
| getSourceViewer().getTextWidget().setTabs(tabWidth); |
| } |
| |
| fEditorSelectionChangedListener = new EditorSelectionChangedListener(); |
| fEditorSelectionChangedListener.install(getSelectionProvider()); |
| |
| installSemanticHighlighting(); |
| } |
| |
| @Override |
| public void dispose() { |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| AnalysisServerData analysisServerData = DartCore.getAnalysisServerData(); |
| String file = getInputFilePath(); |
| if (file != null) { |
| analysisServerData.removeNavigationListener(file, navigationListener); |
| analysisServerData.removeOutlineListener(file, outlineListener); |
| } |
| } |
| |
| DartX.todo("folding"); |
| if (fProjectionModelUpdater != null) { |
| fProjectionModelUpdater.uninstall(); |
| fProjectionModelUpdater = null; |
| } |
| |
| if (fProjectionSupport != null) { |
| fProjectionSupport.dispose(); |
| fProjectionSupport = null; |
| } |
| |
| uninstallOccurrencesFinder(); |
| uninstallOverrideIndicator(); |
| uninstallSemanticHighlighting(); |
| |
| if (fEncodingSupport != null) { |
| fEncodingSupport.dispose(); |
| fEncodingSupport = null; |
| } |
| |
| if (fBracketMatcher != null) { |
| fBracketMatcher.dispose(); |
| fBracketMatcher = null; |
| } |
| |
| if (fSelectionHistory != null) { |
| fSelectionHistory.dispose(); |
| fSelectionHistory = null; |
| } |
| |
| if (fEditorSelectionChangedListener != null) { |
| fEditorSelectionChangedListener.uninstall(getSelectionProvider()); |
| fEditorSelectionChangedListener = null; |
| } |
| |
| if (fActionGroups != null) { |
| fActionGroups.dispose(); |
| fActionGroups = null; |
| } |
| |
| selectionProvider = null; |
| |
| super.dispose(); |
| |
| resolvedUnit = null; |
| } |
| |
| /** |
| * Run the editor format action. |
| */ |
| public void doFormat() { |
| getAction(DartEditorActionDefinitionIds.QUICK_FORMAT).run(); |
| } |
| |
| @Override |
| public void editorContextMenuAboutToShow(IMenuManager menu) { |
| menu.add(new Separator(ITextEditorActionConstants.GROUP_OPEN)); |
| menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT)); |
| menu.add(new Separator(ITextEditorActionConstants.GROUP_RESTORE)); |
| menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); |
| |
| ISelection selection = createElementSelection(); |
| |
| // Open Declaration action |
| ActionContext context = new ActionContext(selection); |
| setContextMenuContext(menu, context); // This context contains a DartElementSelection for menus. |
| |
| // Quick Type Hierarchy |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| IAction action = getAction(DartEditorActionDefinitionIds.OPEN_HIERARCHY); |
| if (action != null && action.isEnabled()) { |
| menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, action); |
| } |
| } else { |
| if (selection instanceof DartSelection) { |
| DartSelection dartSelection = (DartSelection) selection; |
| if (ActionUtil.isOpenHierarchyAvailable(dartSelection)) { |
| IAction action = getAction(DartEditorActionDefinitionIds.OPEN_HIERARCHY); |
| menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, action); |
| } |
| } |
| } |
| |
| // Quick Outline |
| if ((selection instanceof TextSelection) && ((TextSelection) selection).getLength() == 0) { |
| IAction action = getAction(DartEditorActionDefinitionIds.SHOW_OUTLINE); |
| menu.appendToGroup(ITextEditorActionConstants.GROUP_RESTORE, action); |
| } |
| |
| // Revert action |
| addAction( |
| menu, |
| ITextEditorActionConstants.GROUP_RESTORE, |
| ITextEditorActionConstants.REVERT_TO_SAVED); |
| |
| // Cut/Copy/Paste actions |
| addAction(menu, ITextEditorActionConstants.GROUP_EDIT, ITextEditorActionConstants.UNDO); |
| addAction(menu, ITextEditorActionConstants.GROUP_EDIT, ITextEditorActionConstants.CUT); |
| addAction(menu, ITextEditorActionConstants.GROUP_EDIT, ITextEditorActionConstants.COPY); |
| addAction(menu, ITextEditorActionConstants.GROUP_EDIT, ITextEditorActionConstants.PASTE); |
| |
| // Quick Assist |
| { |
| IAction action = getAction(ITextEditorActionConstants.QUICK_ASSIST); |
| if (action != null && action.isEnabled()) { |
| addAction( |
| menu, |
| RefactorActionGroup_NEW.GROUP_REORG, |
| ITextEditorActionConstants.QUICK_ASSIST); |
| } |
| } |
| |
| // Format |
| IAction action = getAction(DartEditorActionDefinitionIds.QUICK_FORMAT); |
| if (action != null && action.isEnabled()) { |
| addAction( |
| menu, |
| RefactorActionGroup_NEW.GROUP_REORG, |
| DartEditorActionDefinitionIds.QUICK_FORMAT); |
| } |
| |
| if (selection instanceof DartSelection) { |
| DartSelection dartSelection = (DartSelection) selection; |
| if (ActionUtil.hasItemsInGroup(menu, IContextMenuConstants.GROUP_OPEN)) { |
| showSelectionLabel.update(dartSelection); |
| showSelectionLabel.setEnabled(false); |
| if (showSelectionLabel.getText() != null) { |
| menu.prependToGroup(IContextMenuConstants.GROUP_OPEN, showSelectionLabel); |
| } |
| } |
| } |
| } |
| |
| @SuppressWarnings("rawtypes") |
| @Override |
| public Object getAdapter(Class required) { |
| |
| DartX.todo("outline"); |
| if (IContentOutlinePage.class.equals(required)) { |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| if (fOutlinePage_NEW == null) { |
| fOutlinePage_NEW = createOutlinePage_NEW(); |
| updateOutlinePageNew(lastOutline); |
| } |
| return fOutlinePage_NEW; |
| } else { |
| if (fOutlinePage_OLD == null) { |
| fOutlinePage_OLD = createOutlinePage_OLD(); |
| } |
| return fOutlinePage_OLD; |
| } |
| } |
| |
| if (IEncodingSupport.class.equals(required)) { |
| return fEncodingSupport; |
| } |
| |
| if (required == IShowInTargetList.class) { |
| return new IShowInTargetList() { |
| @Override |
| public String[] getShowInTargetIds() { |
| String explorerViewID = ProductProperties.getProperty(IProductConstants.PERSPECTIVE_EXPLORER_VIEW); |
| // make sure the specified view ID is known |
| if (PlatformUI.getWorkbench().getViewRegistry().find(explorerViewID) == null) { |
| explorerViewID = IPageLayout.ID_PROJECT_EXPLORER; |
| } |
| return new String[] {explorerViewID, IPageLayout.ID_OUTLINE, IPageLayout.ID_RES_NAV}; |
| } |
| |
| }; |
| } |
| |
| DartX.todo("hover"); |
| if (required == IShowInSource.class) { |
| return new IShowInSource() { |
| @Override |
| public ShowInContext getShowInContext() { |
| return new ShowInContext(getEditorInput(), null) { |
| @Override |
| public ISelection getSelection() { |
| return null; |
| } |
| }; |
| } |
| }; |
| } |
| |
| DartX.todo("folding"); |
| if (required == IDartFoldingStructureProvider.class) { |
| return fProjectionModelUpdater; |
| } |
| |
| if (fProjectionSupport != null) { |
| Object adapter = fProjectionSupport.getAdapter(getSourceViewer(), required); |
| if (adapter != null) { |
| return adapter; |
| } |
| } |
| |
| if (required == IContextProvider.class) { |
| return DartUIHelp.getHelpContextProvider(this, DartHelpContextIds.JAVA_EDITOR); |
| } |
| |
| return super.getAdapter(required); |
| } |
| |
| /** |
| * @return the {@link AssistContext} with resolved {@link CompilationUnit}, selection and |
| * {@link SearchEngine}. May be <code>null</code> if underlying {@link CompilationUnit} is |
| * not resolved. |
| */ |
| public AssistContext getAssistContext() { |
| ITextSelection textSelection = (ITextSelection) getSelectionProvider().getSelection(); |
| return getAssistContext(textSelection); |
| } |
| |
| /** |
| * Returns the cached selected range, which allows to query it from a non-UI thread. |
| * <p> |
| * The result might be outdated if queried from a non-UI thread.</em> |
| * </p> |
| * |
| * @return the caret offset in the master document |
| * @see ITextViewer#getSelectedRange() |
| */ |
| public Point getCachedSelectedRange() { |
| return fCachedSelectedRange; |
| } |
| |
| /** |
| * Answer the {@link DartReconcilingStrategy} associated with this editor. |
| * |
| * @return the strategy or {@code null} if none |
| */ |
| public DartReconcilingStrategy getDartReconcilingStrategy() { |
| return null; |
| } |
| |
| public Point getDocumentSelectionRange() { |
| ISourceViewer sourceViewer = getSourceViewer(); |
| if (sourceViewer == null) { |
| return null; |
| } |
| |
| StyledText styledText = sourceViewer.getTextWidget(); |
| if (styledText == null) { |
| return null; |
| } |
| |
| int widgetOffset = styledText.getCaretOffset(); |
| int widgetLength = styledText.getSelection().y; |
| if (sourceViewer instanceof ITextViewerExtension5) { |
| ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer; |
| int docOffset = extension.widgetOffset2ModelOffset(widgetOffset); |
| return new Point(docOffset, widgetLength); |
| } else { |
| int offset = sourceViewer.getVisibleRegion().getOffset(); |
| int docOffset = offset + widgetOffset; |
| return new Point(docOffset, widgetLength); |
| } |
| } |
| |
| @Override |
| public AnalysisContext getInputAnalysisContext() { |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| throw new IllegalStateException("This method cannot be used with Analysis Server enabled."); |
| } |
| if (inputResourceFile != null) { |
| return DartCore.getProjectManager().getContext(inputResourceFile); |
| } |
| if (inputJavaFile != null) { |
| return DartCore.getProjectManager().getSdkContext(); |
| } |
| return null; |
| } |
| |
| /** |
| * Alternative to {@link #getInputDartElement()} that returns the Analysis engine |
| * {@link com.google.dart.engine.element.Element} instead of a {@link DartElement}. |
| */ |
| public com.google.dart.engine.element.CompilationUnitElement getInputElement() { |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| throw new IllegalStateException("This method cannot be used with Analysis Server enabled."); |
| } |
| com.google.dart.engine.ast.CompilationUnit unit = getInputUnit(); |
| return unit == null ? null : unit.getElement(); |
| } |
| |
| @Override |
| public String getInputFilePath() { |
| // may be workspace IFile |
| if (inputResourceFile != null) { |
| IPath location = inputResourceFile.getLocation(); |
| if (location == null) { |
| return null; |
| } |
| return location.toOSString(); |
| } |
| // may be Java file |
| if (inputJavaFile != null) { |
| return inputJavaFile.getAbsolutePath(); |
| } |
| // TODO(scheglov) Analysis Server |
| return null; |
| } |
| |
| @Override |
| public Project getInputProject() { |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| throw new IllegalStateException("This method cannot be used with Analysis Server enabled."); |
| } |
| if (inputResourceFile != null) { |
| IProject resourceProject = inputResourceFile.getProject(); |
| return DartCore.getProjectManager().getProject(resourceProject); |
| } |
| return null; |
| } |
| |
| /** |
| * @return the input {@link IFile}, may be <code>null</code> if different kind of input. |
| */ |
| public IFile getInputResourceFile() { |
| return inputResourceFile; |
| } |
| |
| @Override |
| public Source getInputSource() { |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| throw new IllegalStateException("This method should not be used with Server."); |
| } |
| ProjectManager projectManager = DartCore.getProjectManager(); |
| // may be workspace IFile |
| if (inputResourceFile != null) { |
| return projectManager.getSource(inputResourceFile); |
| } |
| // may be SDK |
| if (inputJavaFile != null) { |
| DartSdk sdk = projectManager.getSdk(); |
| if (sdk instanceof DirectoryBasedDartSdk) { |
| if (inputJavaFile.getAbsolutePath().startsWith( |
| ((DirectoryBasedDartSdk) sdk).getDirectory().getAbsolutePath() + File.separator)) { |
| return sdk.fromFileUri(inputJavaFile.toURI()); |
| } |
| } |
| return new FileBasedSource(inputJavaFile); |
| } |
| // some random external file |
| return null; |
| } |
| |
| public com.google.dart.engine.ast.CompilationUnit getInputUnit() { |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| throw new IllegalStateException("This method cannot be used with Analysis Server enabled."); |
| } |
| return resolvedUnit; |
| } |
| |
| @Override |
| public int getOrientation() { |
| return SWT.LEFT_TO_RIGHT; // Dart editors are always left to right by default |
| } |
| |
| /** |
| * Returns the latest known outline. |
| */ |
| public Outline getOutline() { |
| return outline; |
| } |
| |
| public IPreferenceStore getPreferences() { |
| return super.getPreferenceStore(); |
| } |
| |
| @Override |
| public ISelectionProvider getSelectionProvider() { |
| return selectionProvider; |
| } |
| |
| /** |
| * @return the last reported text selection range in underlying {@link #getSourceViewer()}. May be |
| * <code>null</code> if selection in not known yet. This method will not make any UI |
| * method invocation. |
| */ |
| public SourceRange getTextSelectionRange() { |
| return textSelectionRange; |
| } |
| |
| @Override |
| public String getTitleToolTip() { |
| if (getEditorInput() instanceof IFileEditorInput) { |
| IFileEditorInput input = (IFileEditorInput) getEditorInput(); |
| |
| if (input.getFile().getLocation() != null) { |
| return input.getFile().getLocation().toFile().toString(); |
| } |
| } |
| |
| return super.getTitleToolTip(); |
| } |
| |
| public final ISourceViewer getViewer() { |
| return getSourceViewer(); |
| } |
| |
| @Override |
| public Annotation gotoAnnotation(boolean forward) { |
| fSelectionChangedViaGotoAnnotation = true; |
| return super.gotoAnnotation(forward); |
| } |
| |
| /** |
| * Jumps to the matching bracket. |
| */ |
| public void gotoMatchingBracket() { |
| |
| ISourceViewer sourceViewer = getSourceViewer(); |
| IDocument document = sourceViewer.getDocument(); |
| if (document == null) { |
| return; |
| } |
| |
| IRegion selection = getSignedSelection(sourceViewer); |
| |
| int selectionLength = Math.abs(selection.getLength()); |
| if (selectionLength > 1) { |
| setStatusLineErrorMessage(DartEditorMessages.GotoMatchingBracket_error_invalidSelection); |
| sourceViewer.getTextWidget().getDisplay().beep(); |
| return; |
| } |
| |
| // #26314 |
| int sourceCaretOffset = selection.getOffset() + selection.getLength(); |
| if (isSurroundedByBrackets(document, sourceCaretOffset)) { |
| sourceCaretOffset -= selection.getLength(); |
| } |
| |
| IRegion region = fBracketMatcher.match(document, sourceCaretOffset); |
| if (region == null) { |
| setStatusLineErrorMessage(DartEditorMessages.GotoMatchingBracket_error_noMatchingBracket); |
| sourceViewer.getTextWidget().getDisplay().beep(); |
| return; |
| } |
| |
| int offset = region.getOffset(); |
| int length = region.getLength(); |
| |
| if (length < 1) { |
| return; |
| } |
| |
| int anchor = fBracketMatcher.getAnchor(); |
| // http://dev.eclipse.org/bugs/show_bug.cgi?id=34195 |
| int targetOffset = ICharacterPairMatcher.RIGHT == anchor ? offset + 1 : offset + length; |
| |
| boolean visible = false; |
| if (sourceViewer instanceof ITextViewerExtension5) { |
| ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer; |
| visible = extension.modelOffset2WidgetOffset(targetOffset) > -1; |
| } else { |
| IRegion visibleRegion = sourceViewer.getVisibleRegion(); |
| // http://dev.eclipse.org/bugs/show_bug.cgi?id=34195 |
| visible = targetOffset >= visibleRegion.getOffset() |
| && targetOffset <= visibleRegion.getOffset() + visibleRegion.getLength(); |
| } |
| |
| if (!visible) { |
| setStatusLineErrorMessage(DartEditorMessages.GotoMatchingBracket_error_bracketOutsideSelectedElement); |
| sourceViewer.getTextWidget().getDisplay().beep(); |
| return; |
| } |
| |
| if (selection.getLength() < 0) { |
| targetOffset -= selection.getLength(); |
| } |
| |
| sourceViewer.setSelectedRange(targetOffset, selection.getLength()); |
| sourceViewer.revealRange(targetOffset, selection.getLength()); |
| } |
| |
| @Override |
| public boolean isDirty() { |
| return isContentEditable() ? super.isDirty() : false; |
| } |
| |
| @Override |
| public boolean isEditable() { |
| return isContentEditable() ? super.isEditable() : false; |
| } |
| |
| @Override |
| public boolean isEditorInputModifiable() { |
| return isContentEditable() ? super.isEditorInputModifiable() : false; |
| } |
| |
| @Override |
| public boolean isEditorInputReadOnly() { |
| return isContentEditable() ? super.isEditorInputReadOnly() : true; |
| } |
| |
| /** |
| * @return {@code true} if the editor's content is visible |
| */ |
| @Override |
| public boolean isVisible() { |
| ISourceViewer viewer = getViewer(); |
| if (viewer != null) { |
| StyledText widget = viewer.getTextWidget(); |
| if (widget != null) { |
| return widget.isVisible(); |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Informs the editor that its outliner has been closed. |
| */ |
| public void outlinePageClosed() { |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| if (fOutlinePage_NEW != null) { |
| fOutlinePage_NEW = null; |
| resetHighlightRange(); |
| } |
| } else { |
| if (fOutlinePage_OLD != null) { |
| fOutlinePage_OLD = null; |
| resetHighlightRange(); |
| } |
| } |
| } |
| |
| public void removeDartSelectionListener(ISelectionChangedListener listener) { |
| dartSelectionListeners.remove(listener); |
| } |
| |
| /** |
| * Resets the foldings structure according to the folding preferences. |
| */ |
| public void resetProjection() { |
| DartX.todo("folding"); |
| if (fProjectionModelUpdater != null) { |
| fProjectionModelUpdater.initialize(); |
| } |
| } |
| |
| public void selectEndReveal(com.google.dart.engine.element.Element element) { |
| if (element == null || element instanceof CompilationUnitElement) { |
| return; |
| } |
| |
| markInNavigationHistory(); |
| |
| int offset = element.getNameOffset(); |
| int length = element.getDisplayName().length(); |
| selectAndReveal(offset, length); |
| } |
| |
| public void setPreferences(IPreferenceStore store) { |
| uninstallSemanticHighlighting(); |
| super.setPreferenceStore(store); |
| installSemanticHighlighting(); |
| } |
| |
| public void setSelection_NEW(Outline outline, boolean moveCursor) { |
| // validate Outline |
| if (outline == null) { |
| return; |
| } |
| // prepare range |
| int offset = outline.getElement().getLocation().getOffset(); |
| int length = outline.getElement().getLocation().getLength(); |
| // prepare ISourceViewer |
| ISourceViewer sourceViewer = getSourceViewer(); |
| if (sourceViewer == null) { |
| return; |
| } |
| // highlight range (not selection - just highlighting on left editor band) |
| if (offset < 0) { |
| return; |
| } |
| setHighlightRange(offset, length, moveCursor); |
| // do we want to change selection? |
| if (!moveCursor) { |
| return; |
| } |
| // prepare StyledText |
| StyledText textWidget = sourceViewer.getTextWidget(); |
| if (textWidget == null) { |
| return; |
| } |
| // set selection in StyledText |
| try { |
| textWidget.setRedraw(false); |
| sourceViewer.revealRange(offset, length); |
| sourceViewer.setSelectedRange(offset, length); |
| } finally { |
| textWidget.setRedraw(true); |
| } |
| } |
| |
| public void setSelection_OLD(LightNodeElement element, boolean moveCursor) { |
| // validate LightNodeElement |
| if (element == null) { |
| return; |
| } |
| // prepare range |
| int offset = element.getNameOffset(); |
| int length = element.getNameLength(); |
| // prepare ISourceViewer |
| ISourceViewer sourceViewer = getSourceViewer(); |
| if (sourceViewer == null) { |
| return; |
| } |
| // highlight range (not selection - just highlighting on left editor band) |
| if (offset < 0) { |
| return; |
| } |
| setHighlightRange(offset, length, moveCursor); |
| // do we want to change selection? |
| if (!moveCursor) { |
| return; |
| } |
| // prepare StyledText |
| StyledText textWidget = sourceViewer.getTextWidget(); |
| if (textWidget == null) { |
| return; |
| } |
| // set selection in StyledText |
| try { |
| textWidget.setRedraw(false); |
| sourceViewer.revealRange(offset, length); |
| sourceViewer.setSelectedRange(offset, length); |
| } finally { |
| textWidget.setRedraw(true); |
| } |
| } |
| |
| /** |
| * Synchronizes the outliner selection with the actual cursor position in the editor. |
| */ |
| public void synchronizeOutlinePageSelection() { |
| |
| // TODO(scheglov) |
| // synchronizeOutlinePage(computeHighlightRangeSourceElement()); |
| } |
| |
| public void updatedTitleImage(Image image) { |
| setTitleImage(image); |
| } |
| |
| @Override |
| protected void adjustHighlightRange(int offset, int length) { |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| if (fOutlinePage_NEW != null) { |
| fOutlinePage_NEW.select(offset); |
| } |
| } else { |
| Object element = getElementAt(offset, false); |
| |
| if (element instanceof LightNodeElement) { |
| LightNodeElement sourceElement = (LightNodeElement) element; |
| int elementOffset = sourceElement.getNameOffset(); |
| int elementLength = sourceElement.getNameLength(); |
| |
| ISourceViewer viewer = getSourceViewer(); |
| if (viewer instanceof ITextViewerExtension5) { |
| ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; |
| extension.exposeModelRange(new Region(elementOffset, elementLength)); |
| } |
| |
| setHighlightRange(elementOffset, elementLength, true); |
| if (fOutlinePage_OLD != null) { |
| fOutlinePage_OLD.select((LightNodeElement) element); |
| } |
| } |
| } |
| |
| ISourceViewer viewer = getSourceViewer(); |
| if (viewer instanceof ITextViewerExtension5) { |
| ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; |
| extension.exposeModelRange(new Region(offset, length)); |
| } else { |
| resetHighlightRange(); |
| } |
| |
| } |
| |
| /** |
| * Determines whether the preference change encoded by the given event changes the override |
| * indication. |
| * |
| * @param event the event to be investigated |
| * @return <code>true</code> if event causes a change |
| */ |
| protected boolean affectsOverrideIndicatorAnnotations(PropertyChangeEvent event) { |
| String key = event.getProperty(); |
| AnnotationPreference preference = getAnnotationPreferenceLookup().getAnnotationPreference( |
| OverrideIndicatorManager.ANNOTATION_TYPE); |
| if (key == null || preference == null) { |
| return false; |
| } |
| |
| return key.equals(preference.getHighlightPreferenceKey()) |
| || key.equals(preference.getVerticalRulerPreferenceKey()) |
| || key.equals(preference.getOverviewRulerPreferenceKey()) |
| || key.equals(preference.getTextPreferenceKey()); |
| } |
| |
| @Override |
| protected boolean affectsTextPresentation(PropertyChangeEvent event) { |
| return ((DartSourceViewerConfiguration) getSourceViewerConfiguration()).affectsTextPresentation(event) |
| || super.affectsTextPresentation(event); |
| } |
| |
| protected void checkEditableState() { |
| // isEditableStateKnown = false; |
| } |
| |
| @Override |
| protected String[] collectContextMenuPreferencePages() { |
| String[] inheritedPages = super.collectContextMenuPreferencePages(); |
| int length = 10; |
| String[] result = new String[inheritedPages.length + length]; |
| result[0] = "com.google.dart.tools.ui.internal.preferences.JavaEditorPreferencePage"; //$NON-NLS-1$ |
| result[1] = "com.google.dart.tools.ui.internal.preferences.JavaTemplatePreferencePage"; //$NON-NLS-1$ |
| result[2] = "com.google.dart.tools.ui.internal.preferences.CodeAssistPreferencePage"; //$NON-NLS-1$ |
| result[3] = "com.google.dart.tools.ui.internal.preferences.CodeAssistPreferenceAdvanced"; //$NON-NLS-1$ |
| result[4] = "com.google.dart.tools.ui.internal.preferences.JavaEditorHoverPreferencePage"; //$NON-NLS-1$ |
| result[5] = "com.google.dart.tools.ui.internal.preferences.JavaEditorColoringPreferencePage"; //$NON-NLS-1$ |
| result[6] = "com.google.dart.tools.ui.internal.preferences.FoldingPreferencePage"; //$NON-NLS-1$ |
| result[7] = "com.google.dart.tools.ui.internal.preferences.MarkOccurrencesPreferencePage"; //$NON-NLS-1$ |
| result[8] = "com.google.dart.tools.ui.internal.preferences.SmartTypingPreferencePage"; //$NON-NLS-1$ |
| result[9] = "com.google.dart.tools.ui.internal.preferences.SaveParticipantPreferencePage"; //$NON-NLS-1$ |
| System.arraycopy(inheritedPages, 0, result, length, inheritedPages.length); |
| return result; |
| } |
| |
| /** |
| * Computes and returns the source element that includes the caret and serves as provider for the |
| * outline page selection and the editor range indication. |
| * <p> |
| * to replace {@link #computeHighlightRangeSourceReference()}. |
| * |
| * @return the computed source element |
| */ |
| protected LightNodeElement computeHighlightRangeSourceElement( |
| com.google.dart.engine.ast.CompilationUnit unit, int caret) { |
| if (unit == null) { |
| return null; |
| } |
| |
| // ISourceViewer sourceViewer = getSourceViewer(); |
| // if (sourceViewer == null) { |
| // return null; |
| // } |
| // |
| // StyledText styledText = sourceViewer.getTextWidget(); |
| // if (styledText == null) { |
| // return null; |
| // } |
| // |
| // int caret = 0; |
| // if (sourceViewer instanceof ITextViewerExtension5) { |
| // ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer; |
| // caret = extension.widgetOffset2ModelOffset(styledText.getCaretOffset()); |
| // } else { |
| // int offset = sourceViewer.getVisibleRegion().getOffset(); |
| // caret = offset + styledText.getCaretOffset(); |
| // } |
| |
| AstNode node = new NodeLocator(caret).searchWithin(unit); |
| |
| // May be whitespace between class declaration {}, try to find class member. |
| if (node instanceof ClassDeclaration) { |
| ClassDeclaration classDeclaration = (ClassDeclaration) node; |
| if (classDeclaration.getLeftBracket().getOffset() + 1 < caret |
| && caret < classDeclaration.getRightBracket().getOffset()) { |
| for (ClassMember member : classDeclaration.getMembers()) { |
| if (caret < member.getOffset()) { |
| node = member; |
| break; |
| } |
| } |
| } |
| } |
| |
| // May be unit whitespace, try to find unit member. |
| if (node instanceof com.google.dart.engine.ast.CompilationUnit) { |
| NodeList<CompilationUnitMember> declarations = ((com.google.dart.engine.ast.CompilationUnit) node).getDeclarations(); |
| for (CompilationUnitMember member : declarations) { |
| if (caret < member.getOffset()) { |
| node = member; |
| break; |
| } |
| } |
| } |
| |
| return LightNodeElements.createLightNodeElement(inputResourceFile, node); |
| } |
| |
| /** |
| * Computes and returns the source reference that includes the caret and serves as provider for |
| * the outline page selection and the editor range indication. |
| * |
| * @return the computed source reference |
| */ |
| protected SourceReference computeHighlightRangeSourceReference() { |
| ISourceViewer sourceViewer = getSourceViewer(); |
| if (sourceViewer == null) { |
| return null; |
| } |
| |
| StyledText styledText = sourceViewer.getTextWidget(); |
| if (styledText == null) { |
| return null; |
| } |
| |
| int caret = 0; |
| if (sourceViewer instanceof ITextViewerExtension5) { |
| ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer; |
| caret = extension.widgetOffset2ModelOffset(styledText.getCaretOffset()); |
| } else { |
| int offset = sourceViewer.getVisibleRegion().getOffset(); |
| caret = offset + styledText.getCaretOffset(); |
| } |
| |
| Object element = getElementAt(caret, false); |
| |
| if (!(element instanceof SourceReference)) { |
| return null; |
| } |
| |
| return (SourceReference) element; |
| } |
| |
| @Override |
| protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) { |
| support.setCharacterPairMatcher(fBracketMatcher); |
| support.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR); |
| super.configureSourceViewerDecorationSupport(support); |
| support.setMarginPainterPreferenceKeys( |
| DartFormatter.PRINT_MARGIN, |
| DartFormatter.PRINT_MARGIN_COLOR, |
| DartFormatter.PRINT_MARGIN_COLUMN); |
| } |
| |
| @Override |
| protected void createActions() { |
| installEncodingSupport(); |
| |
| super.createActions(); |
| |
| DartX.todo("actions"); |
| ActionGroup oeg, ovg; |
| ActionGroup dsg, ddg; |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| fActionGroups = new CompositeActionGroup(new ActionGroup[] { |
| oeg = new OpenEditorActionGroup_NEW(this), ovg = new OpenViewActionGroup_NEW(this), |
| dsg = new DartSearchActionGroup_NEW(this)}); |
| fOpenEditorActionGroup = new CompositeActionGroup(new ActionGroup[] {ovg, oeg, dsg}); |
| } else { |
| fActionGroups = new CompositeActionGroup(new ActionGroup[] { |
| oeg = new OpenEditorActionGroup_OLD(this), ovg = new OpenViewActionGroup_OLD(this), |
| dsg = new DartSearchActionGroup_OLD(this), ddg = new DartdocActionGroup_OLD(this)}); |
| fOpenEditorActionGroup = new CompositeActionGroup(new ActionGroup[] {ovg, oeg, dsg, ddg}); |
| } |
| |
| // Registers the folding actions with the editor |
| fFoldingGroup = new FoldingActionGroup(this, getViewer()); |
| |
| Action action = new GotoMatchingBracketAction(this); |
| action.setActionDefinitionId(DartEditorActionDefinitionIds.GOTO_MATCHING_BRACKET); |
| setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action); |
| |
| action = new TextOperationAction( |
| DartEditorMessages.getBundleForConstructedKeys(), |
| "ShowOutline.", this, DartSourceViewer.SHOW_OUTLINE, true); //$NON-NLS-1$ |
| action.setActionDefinitionId(DartEditorActionDefinitionIds.SHOW_OUTLINE); |
| setAction(DartEditorActionDefinitionIds.SHOW_OUTLINE, action); |
| PlatformUI.getWorkbench().getHelpSystem().setHelp( |
| action, |
| DartHelpContextIds.SHOW_OUTLINE_ACTION); |
| |
| action = new TextOperationAction( |
| DartEditorMessages.getBundleForConstructedKeys(), |
| "OpenStructure.", this, DartSourceViewer.OPEN_STRUCTURE, true); //$NON-NLS-1$ |
| action.setActionDefinitionId(DartEditorActionDefinitionIds.OPEN_STRUCTURE); |
| setAction(DartEditorActionDefinitionIds.OPEN_STRUCTURE, action); |
| PlatformUI.getWorkbench().getHelpSystem().setHelp( |
| action, |
| DartHelpContextIds.OPEN_STRUCTURE_ACTION); |
| |
| action = new TextOperationAction( |
| DartEditorMessages.getBundleForConstructedKeys(), |
| "OpenHierarchy.", this, DartSourceViewer.SHOW_HIERARCHY, true); //$NON-NLS-1$ |
| action.setActionDefinitionId(DartEditorActionDefinitionIds.OPEN_HIERARCHY); |
| setAction(DartEditorActionDefinitionIds.OPEN_HIERARCHY, action); |
| PlatformUI.getWorkbench().getHelpSystem().setHelp( |
| action, |
| DartHelpContextIds.OPEN_HIERARCHY_ACTION); |
| |
| fSelectionHistory = new SelectionHistory(this); |
| |
| if (!DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| action = new StructureSelectEnclosingAction(this, fSelectionHistory); |
| action.setActionDefinitionId(DartEditorActionDefinitionIds.SELECT_ENCLOSING); |
| setAction(StructureSelectionAction.ENCLOSING, action); |
| |
| action = new StructureSelectNextAction(this, fSelectionHistory); |
| action.setActionDefinitionId(DartEditorActionDefinitionIds.SELECT_NEXT); |
| setAction(StructureSelectionAction.NEXT, action); |
| |
| action = new StructureSelectPreviousAction(this, fSelectionHistory); |
| action.setActionDefinitionId(DartEditorActionDefinitionIds.SELECT_PREVIOUS); |
| setAction(StructureSelectionAction.PREVIOUS, action); |
| |
| StructureSelectHistoryAction historyAction = new StructureSelectHistoryAction( |
| this, |
| fSelectionHistory); |
| historyAction.setActionDefinitionId(DartEditorActionDefinitionIds.SELECT_LAST); |
| setAction(StructureSelectionAction.HISTORY, historyAction); |
| fSelectionHistory.setHistoryAction(historyAction); |
| } |
| |
| action = GoToNextPreviousMemberAction.newGoToNextMemberAction(this); |
| action.setActionDefinitionId(DartEditorActionDefinitionIds.GOTO_NEXT_MEMBER); |
| setAction(GoToNextPreviousMemberAction.NEXT_MEMBER, action); |
| |
| action = GoToNextPreviousMemberAction.newGoToPreviousMemberAction(this); |
| action.setActionDefinitionId(DartEditorActionDefinitionIds.GOTO_PREVIOUS_MEMBER); |
| setAction(GoToNextPreviousMemberAction.PREVIOUS_MEMBER, action); |
| |
| action = new FormatElementAction(); |
| action.setActionDefinitionId(DartEditorActionDefinitionIds.QUICK_FORMAT); |
| setAction(DartEditorActionDefinitionIds.QUICK_FORMAT, action); |
| markAsStateDependentAction(DartEditorActionDefinitionIds.QUICK_FORMAT, true); |
| |
| action = new RemoveOccurrenceAnnotations(this); |
| action.setActionDefinitionId(DartEditorActionDefinitionIds.REMOVE_OCCURRENCE_ANNOTATIONS); |
| setAction("RemoveOccurrenceAnnotations", action); //$NON-NLS-1$ |
| |
| // add annotation actions for roll-over expand hover |
| action = new DartSelectMarkerRulerAction2( |
| DartEditorMessages.getBundleForConstructedKeys(), |
| "Editor.RulerAnnotationSelection.", this); //$NON-NLS-1$ |
| setAction("AnnotationAction", action); //$NON-NLS-1$ |
| |
| DartX.todo(); |
| // action = new ShowInPackageViewAction(this); |
| // action.setActionDefinitionId(IJavaEditorActionDefinitionIds.SHOW_IN_PACKAGE_VIEW); |
| // setAction("ShowInPackageView", action); //$NON-NLS-1$ |
| |
| // replace cut/copy paste actions with a version that implement 'add imports |
| // on paste' |
| |
| action = new ClipboardOperationAction( |
| DartEditorMessages.getBundleForConstructedKeys(), |
| "Editor.Cut.", this, ITextOperationTarget.CUT); //$NON-NLS-1$ |
| setAction(ITextEditorActionConstants.CUT, action); |
| |
| action = new ClipboardOperationAction( |
| DartEditorMessages.getBundleForConstructedKeys(), |
| "Editor.Copy.", this, ITextOperationTarget.COPY); //$NON-NLS-1$ |
| setAction(ITextEditorActionConstants.COPY, action); |
| |
| action = new ClipboardOperationAction( |
| DartEditorMessages.getBundleForConstructedKeys(), |
| "Editor.Paste.", this, ITextOperationTarget.PASTE); //$NON-NLS-1$ |
| setAction(ITextEditorActionConstants.PASTE, action); |
| |
| DartX.todo(); |
| // action = new CopyQualifiedNameAction(this); |
| // setAction(IDartEditorActionConstants.COPY_QUALIFIED_NAME, action); |
| |
| removeTrailingWhitespaceAction = new RemoveTrailingWhitespaceAction(getSourceViewer()); |
| } |
| |
| @Override |
| protected IVerticalRulerColumn createAnnotationRulerColumn(CompositeRuler ruler) { |
| DartX.todo(); |
| return super.createAnnotationRulerColumn(ruler); |
| // if (!getPreferenceStore().getBoolean( |
| // PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER)) |
| // return super.createAnnotationRulerColumn(ruler); |
| // |
| // AnnotationRulerColumn column = new AnnotationRulerColumn( |
| // VERTICAL_RULER_WIDTH, getAnnotationAccess()); |
| // column.setHover(new JavaExpandHover(ruler, getAnnotationAccess(), |
| // new IDoubleClickListener() { |
| // |
| // public void doubleClick(DoubleClickEvent event) { |
| // // for now: just invoke ruler double click action |
| // triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK); |
| // } |
| // |
| // private void triggerAction(String actionID) { |
| // IAction action = getAction(actionID); |
| // if (action != null) { |
| // if (action instanceof IUpdate) |
| // ((IUpdate) action).update(); |
| // // hack to propagate line change |
| // if (action instanceof ISelectionListener) { |
| // ((ISelectionListener) action).selectionChanged(null, null); |
| // } |
| // if (action.isEnabled()) |
| // action.run(); |
| // } |
| // } |
| // |
| // })); |
| // |
| // return column; |
| } |
| |
| @Override |
| protected LineChangeHover createChangeHover() { |
| return new DartChangeHover(DartPartitions.DART_PARTITIONING, getOrientation()); |
| } |
| |
| protected ISourceViewer createDartSourceViewer(Composite parent, IVerticalRuler verticalRuler, |
| IOverviewRuler overviewRuler, boolean isOverviewRulerVisible, int styles, |
| IPreferenceStore store) { |
| return new DartSourceViewer( |
| parent, |
| verticalRuler, |
| getOverviewRuler(), |
| isOverviewRulerVisible(), |
| styles, |
| store); |
| } |
| |
| /** |
| * Returns a new Dart source viewer configuration. |
| * |
| * @return a new <code>DartSourceViewerConfiguration</code> |
| */ |
| protected DartSourceViewerConfiguration createDartSourceViewerConfiguration() { |
| DartTextTools textTools = DartToolsPlugin.getDefault().getDartTextTools(); |
| return new DartSourceViewerConfiguration( |
| textTools.getColorManager(), |
| getPreferenceStore(), |
| this, |
| DartPartitions.DART_PARTITIONING); |
| } |
| |
| @Override |
| protected void createNavigationActions() { |
| super.createNavigationActions(); |
| |
| final StyledText textWidget = getSourceViewer().getTextWidget(); |
| |
| IAction action = new SmartLineStartAction(textWidget, false); |
| action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_START); |
| setAction(ITextEditorActionDefinitionIds.LINE_START, action); |
| |
| action = new SmartLineStartAction(textWidget, true); |
| action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_LINE_START); |
| setAction(ITextEditorActionDefinitionIds.SELECT_LINE_START, action); |
| |
| action = new NavigatePreviousSubWordAction(); |
| action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_PREVIOUS); |
| setAction(ITextEditorActionDefinitionIds.WORD_PREVIOUS, action); |
| textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_LEFT, SWT.NULL); |
| |
| action = new NavigateNextSubWordAction(); |
| action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_NEXT); |
| setAction(ITextEditorActionDefinitionIds.WORD_NEXT, action); |
| textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_RIGHT, SWT.NULL); |
| |
| action = new SelectPreviousSubWordAction(); |
| action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS); |
| setAction(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS, action); |
| textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_LEFT, SWT.NULL); |
| |
| action = new SelectNextSubWordAction(); |
| action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT); |
| setAction(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT, action); |
| textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_RIGHT, SWT.NULL); |
| } |
| |
| /** |
| * Creates the outline page used with this editor. |
| * |
| * @return the created Dart outline page |
| */ |
| protected DartOutlinePage_NEW createOutlinePage_NEW() { |
| DartOutlinePage_NEW page = new DartOutlinePage_NEW(fOutlinerContextMenuId, this); |
| setOutlinePageInput_NEW(page, getEditorInput()); |
| return page; |
| } |
| |
| /** |
| * Creates the outline page used with this editor. |
| * |
| * @return the created Dart outline page |
| */ |
| protected DartOutlinePage createOutlinePage_OLD() { |
| DartOutlinePage page = new DartOutlinePage(fOutlinerContextMenuId, this); |
| setOutlinePageInput_OLD(page, getEditorInput()); |
| return page; |
| } |
| |
| @Override |
| protected final ISourceViewer createSourceViewer(Composite parent, IVerticalRuler verticalRuler, |
| int styles) { |
| |
| IPreferenceStore store = getPreferenceStore(); |
| final ISourceViewer viewer = createDartSourceViewer( |
| parent, |
| verticalRuler, |
| getOverviewRuler(), |
| isOverviewRulerVisible(), |
| styles, |
| store); |
| |
| DartUIHelp.setHelp(this, viewer.getTextWidget(), DartHelpContextIds.JAVA_EDITOR); |
| |
| DartSourceViewer dartSourceViewer = null; |
| if (viewer instanceof DartSourceViewer) { |
| dartSourceViewer = (DartSourceViewer) viewer; |
| } |
| |
| /* |
| * This is a performance optimization to reduce the computation of the text presentation |
| * triggered by {@link #setVisibleDocument(IDocument)} |
| */ |
| if (dartSourceViewer != null && isFoldingEnabled() |
| && (store == null || !store.getBoolean(PreferenceConstants.EDITOR_SHOW_SEGMENTS))) { |
| dartSourceViewer.prepareDelayedProjection(); |
| } |
| |
| ProjectionViewer projectionViewer = (ProjectionViewer) viewer; |
| 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$ |
| |
| DartX.todo("hover"); |
| fProjectionSupport.setHoverControlCreator(new IInformationControlCreator() { |
| @Override |
| public IInformationControl createInformationControl(Shell shell) { |
| return new SourceViewerInformationControl( |
| shell, |
| SWT.TOOL | SWT.NO_TRIM | getOrientation(), |
| SWT.NONE, |
| EditorsUI.getTooltipAffordanceString()); |
| } |
| }); |
| fProjectionSupport.setInformationPresenterControlCreator(new IInformationControlCreator() { |
| @Override |
| 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); |
| } |
| }); |
| fProjectionSupport.install(); |
| |
| fProjectionModelUpdater = DartToolsPlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider(); |
| if (fProjectionModelUpdater != null) { |
| fProjectionModelUpdater.install(this, projectionViewer); |
| } |
| |
| // ensure source viewer decoration support has been created and configured |
| getSourceViewerDecorationSupport(viewer); |
| |
| // track text selection range |
| viewer.getTextWidget().addCaretListener(new CaretListener() { |
| @Override |
| public void caretMoved(CaretEvent event) { |
| textSelectionRange = SourceRangeFactory.forStartLength(event.caretOffset, 0); |
| } |
| }); |
| viewer.getTextWidget().addListener(SWT.Selection, new Listener() { |
| @Override |
| public void handleEvent(Event event) { |
| textSelectionRange = SourceRangeFactory.forStartEnd(event.x, event.y); |
| } |
| }); |
| |
| EditorUtility.addGTKPasteHack(viewer); |
| |
| return viewer; |
| } |
| |
| protected void doSelectionChanged(ISelection selection) { |
| if (selection instanceof IStructuredSelection) { |
| IStructuredSelection structuredSelection = (IStructuredSelection) selection; |
| for (Object selectionObject : structuredSelection.toList()) { |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| if (selectionObject instanceof Outline) { |
| setSelection_NEW((Outline) selectionObject, !isActivePart()); |
| break; |
| } |
| } else { |
| if (selectionObject instanceof LightNodeElement) { |
| setSelection_OLD((LightNodeElement) selectionObject, !isActivePart()); |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| @Override |
| protected void doSetInput(IEditorInput input) throws CoreException { |
| inputResourceFile = null; |
| inputJavaFile = null; |
| if (input instanceof IFileEditorInput) { |
| IFileEditorInput fileInput = (IFileEditorInput) input; |
| inputResourceFile = fileInput.getFile(); |
| } else if (input instanceof IURIEditorInput) { |
| IURIEditorInput uriInput = (IURIEditorInput) input; |
| URI uri = uriInput.getURI(); |
| if (uri != null && uri.getScheme().equals("file") && uri.isAbsolute()) { |
| try { |
| inputJavaFile = new File(uri); |
| } catch (Throwable e) { |
| } |
| } |
| } |
| |
| uninstallSemanticHighlighting(); |
| |
| // TODO(scheglov) This code is intentionally left commented. |
| // If we don't follow the "!(sourceViewer instanceof ISourceViewerExtension2)", |
| // it causes https://code.google.com/p/dart/issues/detail?id=18297 |
| // To reproduce it, open editor, rename input file and try to use completion or Quick Assist. |
| // So, we just do it always. |
| { |
| setPreferenceStore(createCombinedPreferenceStore(input)); |
| internalDoSetInput(input); |
| } |
| |
| installSemanticHighlighting(); |
| |
| // ISourceViewer sourceViewer = getSourceViewer(); |
| // if (!(sourceViewer instanceof ISourceViewerExtension2)) { |
| // setPreferenceStore(createCombinedPreferenceStore(input)); |
| // internalDoSetInput(input); |
| // return; |
| // } |
| // |
| // // uninstall & unregister preference store listener |
| // getSourceViewerDecorationSupport(sourceViewer).uninstall(); |
| // ((ISourceViewerExtension2) sourceViewer).unconfigure(); |
| // |
| // setPreferenceStore(createCombinedPreferenceStore(input)); |
| // |
| // // install & register preference store listener |
| // sourceViewer.configure(getSourceViewerConfiguration()); |
| // getSourceViewerDecorationSupport(sourceViewer).install(getPreferenceStore()); |
| // |
| // internalDoSetInput(input); |
| } |
| |
| @Override |
| protected void doSetSelection(ISelection selection) { |
| super.doSetSelection(selection); |
| synchronizeOutlinePageSelection(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * Overrides the default implementation to handle {@link IJavaAnnotation}. |
| * </p> |
| * |
| * @param offset the region offset |
| * @param length the region length |
| * @param forward <code>true</code> for forwards, <code>false</code> for backward |
| * @param annotationPosition the position of the found annotation |
| * @return the found annotation |
| */ |
| @Override |
| protected Annotation findAnnotation(final int offset, final int length, boolean forward, |
| Position annotationPosition) { |
| |
| Annotation nextAnnotation = null; |
| Position nextAnnotationPosition = null; |
| Annotation containingAnnotation = null; |
| Position containingAnnotationPosition = null; |
| boolean currentAnnotation = false; |
| |
| IDocument document = getDocumentProvider().getDocument(getEditorInput()); |
| int endOfDocument = document.getLength(); |
| int distance = Integer.MAX_VALUE; |
| |
| IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput()); |
| @SuppressWarnings("rawtypes") |
| Iterator e = new DartAnnotationIterator(model, true, true); |
| while (e.hasNext()) { |
| Annotation a = (Annotation) e.next(); |
| if (!isNavigationTarget(a)) { |
| continue; |
| } |
| |
| Position p = model.getPosition(a); |
| if (p == null) { |
| continue; |
| } |
| |
| if (forward && p.offset == offset || !forward && p.offset + p.getLength() == offset + length) {// || |
| // p.includes(offset)) |
| // { |
| if (containingAnnotation == null || forward |
| && p.length >= containingAnnotationPosition.length || !forward |
| && p.length >= containingAnnotationPosition.length) { |
| containingAnnotation = a; |
| containingAnnotationPosition = p; |
| currentAnnotation = p.length == length; |
| } |
| } else { |
| int currentDistance = 0; |
| |
| if (forward) { |
| currentDistance = p.getOffset() - offset; |
| if (currentDistance < 0) { |
| currentDistance = endOfDocument + currentDistance; |
| } |
| |
| if (currentDistance < distance || currentDistance == distance |
| && p.length < nextAnnotationPosition.length) { |
| distance = currentDistance; |
| nextAnnotation = a; |
| nextAnnotationPosition = p; |
| } |
| } else { |
| currentDistance = offset + length - (p.getOffset() + p.length); |
| if (currentDistance < 0) { |
| currentDistance = endOfDocument + currentDistance; |
| } |
| |
| if (currentDistance < distance || currentDistance == distance |
| && p.length < nextAnnotationPosition.length) { |
| distance = currentDistance; |
| nextAnnotation = a; |
| nextAnnotationPosition = p; |
| } |
| } |
| } |
| } |
| if (containingAnnotationPosition != null && (!currentAnnotation || nextAnnotation == null)) { |
| annotationPosition.setOffset(containingAnnotationPosition.getOffset()); |
| annotationPosition.setLength(containingAnnotationPosition.getLength()); |
| return containingAnnotation; |
| } |
| if (nextAnnotationPosition != null) { |
| annotationPosition.setOffset(nextAnnotationPosition.getOffset()); |
| annotationPosition.setLength(nextAnnotationPosition.getLength()); |
| } |
| |
| return nextAnnotation; |
| } |
| |
| /** |
| * Returns the standard action group of this editor. |
| * |
| * @return returns this editor's standard action group |
| */ |
| protected ActionGroup getActionGroup() { |
| return fActionGroups; |
| } |
| |
| /** |
| * Returns the most narrow Dart element including the given offset. |
| * |
| * @param offset the offset inside of the requested element |
| * @return the most narrow Dart element |
| */ |
| abstract protected Object /*Element*/getElementAt(int offset); |
| |
| /** |
| * Returns the most narrow Dart element including the given offset. |
| * |
| * @param offset the offset inside of the requested element |
| * @param reconcile <code>true</code> if editor input should be reconciled in advance |
| * @return the most narrow element |
| */ |
| protected Object /*Element*/getElementAt(int offset, boolean reconcile) { |
| return getElementAt(offset); |
| } |
| |
| /** |
| * Returns the folding action group, or <code>null</code> if there is none. |
| * |
| * @return the folding action group, or <code>null</code> if there is none |
| */ |
| protected FoldingActionGroup getFoldingActionGroup() { |
| return fFoldingGroup; |
| } |
| |
| protected ISelectionChangedListener getPatchedSelectionChangedListener() { |
| |
| if (patchedSelectionChangedListener == null) { |
| patchedSelectionChangedListener = new ISelectionChangedListener() { |
| |
| private Runnable runnable = new Runnable() { |
| @Override |
| public void run() { |
| if (isDisposed()) { |
| return; |
| } |
| updateSelectionDependentActions(); |
| } |
| }; |
| |
| private Display display; |
| |
| @Override |
| public void selectionChanged(SelectionChangedEvent event) { |
| Display current = Display.getCurrent(); |
| if (current != null) { |
| // Don't execute asynchronously if we're in a thread that has a display. |
| // Fix for: https://bugs.eclipse.org/bugs/show_bug.cgi?id=368354 (the rationale |
| // is that the actions were not being enabled because they were previously |
| // updated in an async call). |
| // but just patching getSelectionChangedListener() properly. |
| runnable.run(); |
| } else { |
| if (display == null) { |
| display = getSite().getShell().getDisplay(); |
| } |
| display.asyncExec(runnable); |
| } |
| handleCursorPositionChanged(); |
| } |
| }; |
| } |
| |
| return patchedSelectionChangedListener; |
| } |
| |
| /** |
| * Returns the signed current selection. The length will be negative if the resulting selection is |
| * right-to-left (RtoL). |
| * <p> |
| * The selection offset is model based. |
| * </p> |
| * |
| * @param sourceViewer the source viewer |
| * @return a region denoting the current signed selection, for a resulting RtoL selections length |
| * is < 0 |
| */ |
| protected IRegion getSignedSelection(ISourceViewer sourceViewer) { |
| StyledText text = sourceViewer.getTextWidget(); |
| Point selection = text.getSelectionRange(); |
| |
| if (text.getCaretOffset() == selection.x) { |
| selection.x = selection.x + selection.y; |
| selection.y = -selection.y; |
| } |
| |
| selection.x = widgetOffset2ModelOffset(sourceViewer, selection.x); |
| |
| return new Region(selection.x, selection.y); |
| } |
| |
| @Override |
| protected String getStatusBanner(IStatus status) { |
| if (fEncodingSupport != null) { |
| String message = fEncodingSupport.getStatusBanner(status); |
| if (message != null) { |
| return message; |
| } |
| } |
| return super.getStatusBanner(status); |
| } |
| |
| @Override |
| protected String getStatusHeader(IStatus status) { |
| if (fEncodingSupport != null) { |
| String message = fEncodingSupport.getStatusHeader(status); |
| if (message != null) { |
| return message; |
| } |
| } |
| return super.getStatusHeader(status); |
| } |
| |
| @Override |
| protected String getStatusMessage(IStatus status) { |
| if (fEncodingSupport != null) { |
| String message = fEncodingSupport.getStatusMessage(status); |
| if (message != null) { |
| return message; |
| } |
| } |
| return super.getStatusMessage(status); |
| } |
| |
| @Override |
| protected IOperationApprover getUndoRedoOperationApprover(IUndoContext undoContext) { |
| return new NonLocalUndoUserApprover( |
| undoContext, |
| this, |
| new Object[] {inputResourceFile}, |
| IResource.class); |
| } |
| |
| @Override |
| protected void handleCursorPositionChanged() { |
| super.handleCursorPositionChanged(); |
| fCachedSelectedRange = getViewer().getSelectedRange(); |
| } |
| |
| @Override |
| protected void handlePreferenceStoreChanged(PropertyChangeEvent event) { |
| |
| String property = event.getProperty(); |
| |
| try { |
| |
| ISourceViewer sourceViewer = getSourceViewer(); |
| if (sourceViewer == null) { |
| return; |
| } |
| |
| if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) { |
| IPreferenceStore store = getPreferenceStore(); |
| if (store != null) { |
| sourceViewer.getTextWidget().setTabs( |
| store.getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH)); |
| } |
| if (isTabsToSpacesConversionEnabled()) { |
| uninstallTabsToSpacesConverter(); |
| installTabsToSpacesConverter(); |
| } |
| return; |
| } |
| |
| if (isEditorHoverProperty(property)) { |
| updateHoverBehavior(); |
| } |
| |
| boolean newBooleanValue = false; |
| Object newValue = event.getNewValue(); |
| if (newValue != null) { |
| newBooleanValue = Boolean.valueOf(newValue.toString()).booleanValue(); |
| } |
| |
| if (PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE.equals(property)) { |
| if (newBooleanValue) { |
| selectionChanged(); |
| } |
| return; |
| } |
| |
| if (PreferenceConstants.EDITOR_MARK_OCCURRENCES.equals(property)) { |
| if (!newBooleanValue) { |
| uninstallOccurrencesFinder(); |
| } else { |
| installOccurrencesFinder(true); |
| } |
| return; |
| } |
| |
| ((DartSourceViewerConfiguration) getSourceViewerConfiguration()).handlePropertyChangeEvent(event); |
| |
| if (affectsOverrideIndicatorAnnotations(event)) { |
| if (isShowingOverrideIndicators()) { |
| if (fOverrideIndicatorManager == null) { |
| installOverrideIndicator(true); |
| } |
| } else { |
| if (fOverrideIndicatorManager != null) { |
| uninstallOverrideIndicator(); |
| } |
| } |
| return; |
| } |
| |
| if (PreferenceConstants.EDITOR_FOLDING_PROVIDER.equals(property)) { |
| if (sourceViewer instanceof ProjectionViewer) { |
| DartX.todo("folding"); |
| ProjectionViewer projectionViewer = (ProjectionViewer) sourceViewer; |
| if (fProjectionModelUpdater != null) { |
| fProjectionModelUpdater.uninstall(); |
| } |
| // either freshly enabled or provider changed |
| fProjectionModelUpdater = DartToolsPlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider(); |
| if (fProjectionModelUpdater != null) { |
| fProjectionModelUpdater.install(this, projectionViewer); |
| } |
| } |
| return; |
| } |
| |
| if (DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE.equals(property) |
| || DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE.equals(property) |
| || DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR.equals(property)) { |
| StyledText textWidget = sourceViewer.getTextWidget(); |
| int tabWidth = getSourceViewerConfiguration().getTabWidth(sourceViewer); |
| if (textWidget.getTabs() != tabWidth) { |
| textWidget.setTabs(tabWidth); |
| } |
| return; |
| } |
| |
| if (PreferenceConstants.EDITOR_FOLDING_ENABLED.equals(property)) { |
| if (sourceViewer instanceof ProjectionViewer) { |
| new ToggleFoldingRunner().runWhenNextVisible(); |
| } |
| return; |
| } |
| |
| } finally { |
| super.handlePreferenceStoreChanged(event); |
| } |
| |
| if (AbstractDecoratedTextEditorPreferenceConstants.SHOW_RANGE_INDICATOR.equals(property)) { |
| // superclass already installed the range indicator |
| Object newValue = event.getNewValue(); |
| ISourceViewer viewer = getSourceViewer(); |
| if (newValue != null && viewer != null) { |
| if (Boolean.valueOf(newValue.toString()).booleanValue()) { |
| // adjust the highlightrange in order to get the magnet right after |
| // changing the selection |
| Point selection = viewer.getSelectedRange(); |
| adjustHighlightRange(selection.x, selection.y); |
| } |
| } |
| |
| } |
| } |
| |
| @Override |
| protected void initializeDragAndDrop(ISourceViewer viewer) { |
| // Disabled in Dart Editor. |
| // super.initializeDragAndDrop(viewer); |
| } |
| |
| @Override |
| protected void initializeEditor() { |
| IPreferenceStore store = createCombinedPreferenceStore(null); |
| setPreferenceStore(store); |
| setSourceViewerConfiguration(createDartSourceViewerConfiguration()); |
| } |
| |
| @Override |
| protected void initializeKeyBindingScopes() { |
| setKeyBindingScopes(new String[] {"com.google.dart.tools.ui.dartViewScope"}); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Initializes the given viewer's colors. |
| * |
| * @param viewer the viewer to be initialized |
| */ |
| @Override |
| protected void initializeViewerColors(ISourceViewer viewer) { |
| // is handled by DartSourceViewer |
| } |
| |
| /** |
| * Installs the encoding support on the given text editor. |
| * <p> |
| * Subclasses may override to install their own encoding support or to disable the default |
| * encoding support. |
| * </p> |
| */ |
| protected void installEncodingSupport() { |
| fEncodingSupport = new DefaultEncodingSupport(); |
| fEncodingSupport.initialize(this); |
| } |
| |
| protected void installOccurrencesFinder(boolean forceUpdate) { |
| DartSourceViewer viewer = (DartSourceViewer) getSourceViewer(); |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| occurrencesManager_NEW = new MarkOccurrencesManager_NEW( |
| this, |
| viewer, |
| getDartReconcilingStrategy()); |
| } else { |
| occurrencesManager_OLD = new MarkOccurrencesManager_OLD(this, viewer); |
| } |
| } |
| |
| protected void installOverrideIndicator(boolean provideAST) { |
| uninstallOverrideIndicator(); |
| IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput()); |
| if (model == null) { |
| return; |
| } |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| fOverrideIndicatorManager = new OverrideIndicatorManager(model); |
| } else { |
| com.google.dart.engine.ast.CompilationUnit cu = getInputUnit(); |
| fOverrideIndicatorManager = new OverrideIndicatorManager(model, cu); |
| } |
| fOverrideIndicatorManager.install(this); |
| } |
| |
| protected boolean isActivePart() { |
| IWorkbenchPart part = getActivePart(); |
| return part != null && part.equals(this); |
| } |
| |
| protected boolean isMarkingOccurrences() { |
| IPreferenceStore store = getPreferenceStore(); |
| return store != null && store.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES); |
| } |
| |
| /** |
| * Tells whether override indicators are shown. |
| * |
| * @return <code>true</code> if the override indicators are shown |
| */ |
| protected boolean isShowingOverrideIndicators() { |
| AnnotationPreference preference = getAnnotationPreferenceLookup().getAnnotationPreference( |
| OverrideIndicatorManager.ANNOTATION_TYPE); |
| IPreferenceStore store = getPreferenceStore(); |
| return getBoolean(store, preference.getHighlightPreferenceKey()) |
| || getBoolean(store, preference.getVerticalRulerPreferenceKey()) |
| || getBoolean(store, preference.getOverviewRulerPreferenceKey()) |
| || getBoolean(store, preference.getTextPreferenceKey()); |
| } |
| |
| @Override |
| protected boolean isTabsToSpacesConversionEnabled() { |
| return getPreferenceStore() != null |
| && getPreferenceStore().getBoolean( |
| AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS); |
| } |
| |
| @Override |
| protected void performRevert() { |
| ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer(); |
| projectionViewer.setRedraw(false); |
| try { |
| |
| boolean projectionMode = projectionViewer.isProjectionMode(); |
| if (projectionMode) { |
| projectionViewer.disableProjection(); |
| DartX.todo("folding"); |
| if (fProjectionModelUpdater != null) { |
| fProjectionModelUpdater.uninstall(); |
| } |
| } |
| |
| super.performRevert(); |
| |
| if (projectionMode) { |
| DartX.todo("folding"); |
| if (fProjectionModelUpdater != null) { |
| fProjectionModelUpdater.install(this, projectionViewer); |
| } |
| projectionViewer.enableProjection(); |
| } |
| |
| } finally { |
| projectionViewer.setRedraw(true); |
| checkEditableState(); |
| } |
| } |
| |
| @Override |
| protected void performSave(boolean overwrite, IProgressMonitor progressMonitor) { |
| UIInstrumentationBuilder instrumentation = UIInstrumentation.builder("Editor-Save-Perf"); |
| try { |
| |
| performSaveActions(); |
| |
| instrumentation.metric("Save-Actions", "complete"); |
| |
| super.performSave(overwrite, progressMonitor); |
| |
| instrumentation.metric("Save", "complete"); |
| |
| int lines = getDocumentProvider().getDocument(getEditorInput()).getNumberOfLines(); |
| instrumentation.metric("Lines", lines); |
| |
| } finally { |
| instrumentation.log(); |
| } |
| } |
| |
| @Override |
| protected void rulerContextMenuAboutToShow(IMenuManager menu) { |
| super.rulerContextMenuAboutToShow(menu); |
| |
| // Need to remove preferences item from the list; can't supress it via activities |
| // because there is no command defined for this item |
| menu.remove(ITextEditorActionConstants.RULER_PREFERENCES); |
| |
| IAction action = getAction("FoldingToggle"); //$NON-NLS-1$ |
| |
| menu.add(action); |
| action = getAction("FoldingExpandAll"); //$NON-NLS-1$ |
| |
| menu.add(action); |
| action = getAction("FoldingCollapseAll"); //$NON-NLS-1$ |
| |
| menu.add(action); |
| action = getAction("FoldingRestore"); //$NON-NLS-1$ |
| menu.add(action); |
| } |
| |
| /** |
| * React to changed selection. |
| */ |
| protected void selectionChanged() { |
| |
| if (getSelectionProvider() == null) { |
| return; |
| } |
| |
| ISelection selection = getSelectionProvider().getSelection(); |
| // TODO(scheglov) |
| LightNodeElement element = computeHighlightRangeSourceElement( |
| resolvedUnit, |
| ((ITextSelection) selection).getOffset()); |
| setSelectionRange(element, false); |
| |
| if (!fSelectionChangedViaGotoAnnotation) { |
| updateStatusLine(); |
| } |
| fSelectionChangedViaGotoAnnotation = false; |
| } |
| |
| protected void setContextMenuContext(IMenuManager menu, ActionContext context) { |
| fOpenEditorActionGroup.setContext(context); |
| fOpenEditorActionGroup.fillContextMenu(menu); |
| fOpenEditorActionGroup.setContext(null); |
| } |
| |
| /** |
| * Sets the input of the editor's outline page. |
| * |
| * @param page the Dart outline page |
| * @param input the editor input |
| */ |
| protected void setOutlinePageInput_NEW(DartOutlinePage_NEW page, IEditorInput input) { |
| // NOOP |
| } |
| |
| /** |
| * Sets the input of the editor's outline page. |
| * |
| * @param page the Dart outline page |
| * @param input the editor input |
| */ |
| protected void setOutlinePageInput_OLD(DartOutlinePage page, IEditorInput input) { |
| if (page == null) { |
| return; |
| } |
| page.setInput(resolvedUnit); |
| } |
| |
| /** |
| * Sets the outliner's context menu ID. |
| * |
| * @param menuId the menu ID |
| */ |
| protected void setOutlinerContextMenuId(String menuId) { |
| fOutlinerContextMenuId = menuId; |
| } |
| |
| @Override |
| protected void setPreferenceStore(IPreferenceStore store) { |
| super.setPreferenceStore(store); |
| if (getSourceViewerConfiguration() instanceof DartSourceViewerConfiguration) { |
| DartTextTools textTools = DartToolsPlugin.getDefault().getDartTextTools(); |
| setSourceViewerConfiguration(new DartSourceViewerConfiguration( |
| textTools.getColorManager(), |
| store, |
| this, |
| DartPartitions.DART_PARTITIONING)); |
| } |
| if (getSourceViewer() instanceof DartSourceViewer) { |
| ((DartSourceViewer) getSourceViewer()).setPreferenceStore(store); |
| } |
| } |
| |
| protected void setSelection(SourceReference reference, boolean moveCursor) { |
| // NOTUSED |
| if (getSelectionProvider() == null) { |
| return; |
| } |
| |
| ISelection selection = getSelectionProvider().getSelection(); |
| if (selection instanceof ITextSelection) { |
| ITextSelection textSelection = (ITextSelection) selection; |
| // PR 39995: [navigation] Forward history cleared after going back in |
| // navigation history: |
| // mark only in navigation history if the cursor is being moved (which it |
| // isn't if |
| // this is called from a PostSelectionEvent that should only update the |
| // magnet) |
| if (moveCursor && (textSelection.getOffset() != 0 || textSelection.getLength() != 0)) { |
| markInNavigationHistory(); |
| } |
| } |
| |
| if (reference != null) { |
| |
| StyledText textWidget = null; |
| |
| ISourceViewer sourceViewer = getSourceViewer(); |
| if (sourceViewer != null) { |
| textWidget = sourceViewer.getTextWidget(); |
| } |
| |
| if (textWidget == null) { |
| return; |
| } |
| |
| try { |
| SourceRange range = reference.getSourceRange(); |
| |
| if (range == null) { |
| return; |
| } |
| |
| int offset = range.getOffset(); |
| int length = range.getLength(); |
| |
| if (offset < 0 || length < 0) { |
| return; |
| } |
| |
| setHighlightRange(offset, length, moveCursor); |
| |
| if (!moveCursor) { |
| return; |
| } |
| |
| offset = -1; |
| length = -1; |
| |
| range = reference.getNameRange(); |
| if (range != null) { |
| offset = range.getOffset(); |
| length = range.getLength(); |
| } |
| |
| if (offset > -1 && length > 0) { |
| |
| try { |
| textWidget.setRedraw(false); |
| sourceViewer.revealRange(offset, length); |
| sourceViewer.setSelectedRange(offset, length); |
| } finally { |
| textWidget.setRedraw(true); |
| } |
| |
| markInNavigationHistory(); |
| } |
| |
| } catch (DartModelException x) { |
| } catch (IllegalArgumentException x) { |
| } |
| |
| } else if (moveCursor) { |
| resetHighlightRange(); |
| markInNavigationHistory(); |
| } |
| } |
| |
| protected void setSelectionRange(LightNodeElement reference, boolean moveCursor) { |
| if (getSelectionProvider() == null) { |
| return; |
| } |
| ISelection selection = getSelectionProvider().getSelection(); |
| if (selection instanceof ITextSelection) { |
| ITextSelection textSelection = (ITextSelection) selection; |
| // PR 39995: [navigation] Forward history cleared after going back in navigation history: |
| // mark only in navigation history if the cursor is being moved (which it isn't if |
| // this is called from a PostSelectionEvent that should only update the magnet) |
| if (moveCursor && (textSelection.getOffset() != 0 || textSelection.getLength() != 0)) { |
| markInNavigationHistory(); |
| } |
| } |
| if (reference != null) { |
| StyledText textWidget = null; |
| ISourceViewer sourceViewer = getSourceViewer(); |
| if (sourceViewer != null) { |
| textWidget = sourceViewer.getTextWidget(); |
| } |
| if (textWidget == null) { |
| return; |
| } |
| try { |
| int offset = reference.getNode().getOffset(); |
| int length = reference.getNode().getLength(); |
| if (offset < 0 || length < 0) { |
| return; |
| } |
| setHighlightRange(offset, length, moveCursor); |
| if (!moveCursor) { |
| return; |
| } |
| offset = -1; |
| length = -1; |
| offset = reference.getNameOffset(); |
| length = reference.getNameLength(); |
| if (offset > -1 && length > 0) { |
| try { |
| textWidget.setRedraw(false); |
| sourceViewer.revealRange(offset, length); |
| sourceViewer.setSelectedRange(offset, length); |
| } finally { |
| textWidget.setRedraw(true); |
| } |
| markInNavigationHistory(); |
| } |
| } catch (IllegalArgumentException x) { |
| } |
| } else if (moveCursor) { |
| resetHighlightRange(); |
| markInNavigationHistory(); |
| } |
| } |
| |
| /** |
| * Synchronizes the outliner selection with the given element position in the editor. |
| * |
| * @param element the dart element to select |
| */ |
| protected void synchronizeOutlinePage(Object /* Element */element) { |
| synchronizeOutlinePage(element, true); |
| } |
| |
| /** |
| * Synchronizes the outliner selection with the given element position in the editor. |
| * |
| * @param element the Dart element to select |
| * @param checkIfOutlinePageActive <code>true</code> if check for active outline page needs to be |
| * done |
| */ |
| protected void synchronizeOutlinePage(Object /* ASTNode */element, |
| boolean checkIfOutlinePageActive) { |
| if (fOutlinePage_OLD != null && element != null |
| && !(checkIfOutlinePageActive && isOutlinePageActive())) { |
| // TODO(scheglov) |
| // ((DartOutlinePage) fOutlinePage).select((LightNodeElement) element); |
| // ((DartOutlinePage) fOutlinePage).setInput( |
| // (com.google.dart.engine.ast.CompilationUnit) ((LightNodeElement) element).getNode().getRoot(), |
| // (LightNodeElement) element); |
| } |
| } |
| |
| protected void uninstallOccurrencesFinder() { |
| if (occurrencesManager_OLD != null) { |
| occurrencesManager_OLD.dispose(); |
| occurrencesManager_OLD = null; |
| } |
| if (occurrencesManager_NEW != null) { |
| occurrencesManager_NEW.dispose(); |
| occurrencesManager_NEW = null; |
| } |
| } |
| |
| protected void uninstallOverrideIndicator() { |
| if (fOverrideIndicatorManager != null) { |
| fOverrideIndicatorManager.removeAnnotations(); |
| fOverrideIndicatorManager.uninstall(); |
| fOverrideIndicatorManager = null; |
| } |
| } |
| |
| @Override |
| protected void updateMarkerViews(Annotation annotation) { |
| super.updateMarkerViews(annotation); |
| } |
| |
| @Override |
| protected void updatePropertyDependentActions() { |
| super.updatePropertyDependentActions(); |
| if (fEncodingSupport != null) { |
| fEncodingSupport.reset(); |
| } |
| } |
| |
| protected void updateStatusLine() { |
| ITextSelection selection = (ITextSelection) getSelectionProvider().getSelection(); |
| Annotation annotation = getAnnotation(selection.getOffset(), selection.getLength()); |
| setStatusLineErrorMessage(null); |
| setStatusLineMessage(null); |
| if (annotation != null) { |
| updateMarkerViews(annotation); |
| } |
| } |
| |
| boolean isFoldingEnabled() { |
| return DartToolsPlugin.getDefault().getPreferenceStore().getBoolean( |
| PreferenceConstants.EDITOR_FOLDING_ENABLED); |
| } |
| |
| boolean markOccurrencesOfType(/* IBinding */Object binding) { |
| DartX.todo("modifiers,marking"); |
| 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; |
| } |
| |
| /** |
| * Applies the current selection to the Outline view. |
| */ |
| private void applySelectionToOutline() { |
| // prepare selection |
| ISelection selection = getSelectionProvider().getSelection(); |
| if (!(selection instanceof TextSelection)) { |
| return; |
| } |
| int offset = ((TextSelection) selection).getOffset(); |
| // apply selected element |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| if (fOutlinePage_NEW != null) { |
| fOutlinePage_NEW.select(offset); |
| } |
| } else { |
| // prepare resolved unit |
| com.google.dart.engine.ast.CompilationUnit unit = resolvedUnit; |
| if (unit == null) { |
| return; |
| } |
| // apply selected element |
| LightNodeElement element = computeHighlightRangeSourceElement(resolvedUnit, offset); |
| if (element != null && fOutlinePage_OLD != null) { |
| fOutlinePage_OLD.select(element); |
| } |
| } |
| } |
| |
| /** |
| * Creates and returns the preference store for this Dart editor with the given input. |
| * |
| * @param input The editor input for which to create the preference store |
| * @return the preference store for this editor |
| */ |
| private IPreferenceStore createCombinedPreferenceStore(IEditorInput input) { |
| List<IPreferenceStore> stores = new ArrayList<IPreferenceStore>(3); |
| |
| IProject project = EditorUtility.getProject(input); |
| if (project != null) { |
| stores.add(new EclipsePreferencesAdapter(new ProjectScope(project), DartCore.PLUGIN_ID)); |
| } |
| |
| stores.add(DartToolsPlugin.getDefault().getPreferenceStore()); |
| stores.add(new PreferencesAdapter(DartCore.getPlugin().getPluginPreferences())); |
| stores.add(EditorsUI.getPreferenceStore()); |
| |
| return new ChainedPreferenceStore(stores.toArray(new IPreferenceStore[stores.size()])); |
| } |
| |
| /** |
| * Notifies all listeners of {@link DartSelection}. |
| */ |
| private void fireDartSelectionListeners() { |
| ISelection selection = getSelectionProvider().getSelection(); |
| SelectionChangedEvent event = new SelectionChangedEvent(selectionProvider, selection); |
| for (ISelectionChangedListener listener : ImmutableList.copyOf(dartSelectionListeners)) { |
| listener.selectionChanged(event); |
| } |
| } |
| |
| private IWorkbenchPart getActivePart() { |
| IWorkbenchWindow window = getSite().getWorkbenchWindow(); |
| IPartService service = window.getPartService(); |
| IWorkbenchPart part = service.getActivePart(); |
| return part; |
| } |
| |
| /** |
| * Returns the annotation overlapping with the given range or <code>null</code>. |
| * |
| * @param offset the region offset |
| * @param length the region length |
| * @return the found annotation or <code>null</code> |
| */ |
| private Annotation getAnnotation(int offset, int length) { |
| IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput()); |
| @SuppressWarnings("rawtypes") |
| Iterator e = new DartAnnotationIterator(model, true, false); |
| while (e.hasNext()) { |
| Annotation a = (Annotation) e.next(); |
| Position p = model.getPosition(a); |
| if (p != null && p.overlapsWith(offset, length)) { |
| return a; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @return the {@link AssistContext} with resolved {@link CompilationUnit}, selection and |
| * {@link SearchEngine}. May be <code>null</code>. |
| */ |
| private AssistContext getAssistContext(ITextSelection textSelection) { |
| try { |
| // prepare selection |
| if (textSelection == null) { |
| return null; |
| } |
| int selectionOffset = 0; |
| int selectionLength = 0; |
| { |
| selectionOffset = textSelection.getOffset(); |
| selectionLength = textSelection.getLength(); |
| } |
| // TODO(scheglov) Analysis Server |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| String file = getInputFilePath(); |
| if (file == null) { |
| return null; |
| } |
| return new AssistContext(null, null, file, null, null, selectionOffset, selectionLength); |
| } |
| // prepare source |
| Source source = getInputSource(); |
| if (source == null) { |
| return null; |
| } |
| // prepare AnalysisContext |
| AnalysisContext analysisContext = getInputAnalysisContext(); |
| if (analysisContext == null) { |
| return null; |
| } |
| // prepare input CompilationUnit |
| com.google.dart.engine.ast.CompilationUnit unit = getInputUnit(); |
| if (unit == null) { |
| return null; |
| } |
| if (unit.getElement() == null) { |
| return null; |
| } |
| // return AssistContext |
| Index index = DartCore.getProjectManager().getIndex(); |
| return new AssistContext( |
| SearchEngineFactory.createSearchEngine(index), |
| analysisContext, |
| null, |
| source, |
| unit, |
| selectionOffset, |
| selectionLength); |
| } catch (Throwable e) { |
| throw new Error(e); |
| } |
| } |
| |
| /** |
| * Returns the boolean preference for the given key. |
| * |
| * @param store the preference store |
| * @param key the preference key |
| * @return <code>true</code> if the key exists in the store and its value is <code>true</code> |
| */ |
| private boolean getBoolean(IPreferenceStore store, String key) { |
| return key != null && store.getBoolean(key); |
| } |
| |
| /** |
| * Install Semantic Highlighting. |
| */ |
| private void installSemanticHighlighting() { |
| DartSourceViewer viewer = (DartSourceViewer) getSourceViewer(); |
| if (viewer == null) { |
| return; |
| } |
| // TODO(scheglov) Analysis Server: remove this old method |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| AnalysisServerData analysisServerData = DartCore.getAnalysisServerData(); |
| String file = getInputFilePath(); |
| if (file != null) { |
| analysisServerHighlightManager = new SemanticHighlightingManager_NEW( |
| viewer, |
| file, |
| getDartReconcilingStrategy()); |
| } |
| return; |
| } |
| if (fSemanticManager == null) { |
| fSemanticManager = new SemanticHighlightingManager(); |
| fSemanticManager.install( |
| this, |
| viewer, |
| DartToolsPlugin.getDefault().getDartTextTools().getColorManager(), |
| getPreferenceStore()); |
| } |
| } |
| |
| private void internalDoSetInput(IEditorInput input) throws CoreException { |
| ISourceViewer sourceViewer = getSourceViewer(); |
| DartSourceViewer dartSourceViewer = null; |
| if (sourceViewer instanceof DartSourceViewer) { |
| dartSourceViewer = (DartSourceViewer) sourceViewer; |
| } |
| |
| IPreferenceStore store = getPreferenceStore(); |
| if (dartSourceViewer != null && isFoldingEnabled() |
| && (store == null || !store.getBoolean(PreferenceConstants.EDITOR_SHOW_SEGMENTS))) { |
| dartSourceViewer.prepareDelayedProjection(); |
| } |
| |
| try { |
| super.doSetInput(input); |
| } catch (Throwable e) { |
| @SuppressWarnings("restriction") |
| IEditorInput dumyInput = new org.eclipse.ui.internal.part.NullEditorInput(); |
| super.doSetInput(dumyInput); |
| close(false); |
| return; |
| } |
| |
| if (dartSourceViewer != null && dartSourceViewer.getReconciler() == null) { |
| IReconciler reconciler = getSourceViewerConfiguration().getReconciler(dartSourceViewer); |
| if (reconciler != null) { |
| reconciler.install(dartSourceViewer); |
| dartSourceViewer.setReconciler(reconciler); |
| } |
| } |
| |
| if (fEncodingSupport != null) { |
| fEncodingSupport.reset(); |
| } |
| |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| AnalysisServerData analysisServerData = DartCore.getAnalysisServerData(); |
| String file = getInputFilePath(); |
| if (file != null) { |
| analysisServerData.addNavigationListener(file, navigationListener); |
| analysisServerData.addOutlineListener(file, outlineListener); |
| } |
| } |
| |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| setOutlinePageInput_NEW(fOutlinePage_NEW, input); |
| } else { |
| setOutlinePageInput_OLD(fOutlinePage_OLD, input); |
| } |
| |
| if (isShowingOverrideIndicators()) { |
| installOverrideIndicator(false); |
| } |
| } |
| |
| /* |
| * Tells whether the content is editable. |
| */ |
| private boolean isContentEditable() { |
| if (PubCacheManager_NEW.isPubCacheResource(inputResourceFile)) { |
| return false; |
| } |
| return inputResourceFile != null && !DartCore.isContainedInPackages(inputResourceFile) |
| && !inputResourceFile.isReadOnly(); |
| } |
| |
| /** |
| * @return {@code true} if this {@link DartEditor} was already disposed. |
| */ |
| private boolean isDisposed() { |
| return getSourceViewer() == null; |
| } |
| |
| private boolean isEditorHoverProperty(String property) { |
| return PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS.equals(property); |
| } |
| |
| private boolean isOutlinePageActive() { |
| IWorkbenchPart part = getActivePart(); |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| return part instanceof ContentOutline |
| && ((ContentOutline) part).getCurrentPage() == fOutlinePage_NEW; |
| } else { |
| return part instanceof ContentOutline |
| && ((ContentOutline) part).getCurrentPage() == fOutlinePage_OLD; |
| } |
| } |
| |
| private boolean isRemoveTrailingWhitespaceEnabled() { |
| return PreferenceConstants.getPreferenceStore().getBoolean( |
| PreferenceConstants.EDITOR_REMOVE_TRAILING_WS); |
| } |
| |
| private void patchSelectionChangeParticipation() { |
| // To address dartbug.com/7998 |
| //TODO (pquitslund): revisit when we move to 3.8 and see if this hack is still needed |
| getSelectionProvider().removeSelectionChangedListener(getSelectionChangedListener()); |
| getSelectionProvider().addSelectionChangedListener(getPatchedSelectionChangedListener()); |
| } |
| |
| private void performSaveActions() { |
| if (isRemoveTrailingWhitespaceEnabled()) { |
| try { |
| removeTrailingWhitespaceAction.run(); |
| } catch (InvocationTargetException e) { |
| DartToolsPlugin.log(e); |
| } |
| } |
| } |
| |
| /** |
| * Uninstall Semantic Highlighting. |
| */ |
| private void uninstallSemanticHighlighting() { |
| // TODO(scheglov) Analysis Server: remove this old method |
| if (DartCoreDebug.ENABLE_ANALYSIS_SERVER) { |
| if (analysisServerHighlightManager != null) { |
| analysisServerHighlightManager.dispose(); |
| analysisServerHighlightManager = null; |
| } |
| return; |
| } |
| if (fSemanticManager != null) { |
| fSemanticManager.uninstall(); |
| fSemanticManager = null; |
| } |
| } |
| |
| /* |
| * Update the hovering behavior depending on the preferences. |
| */ |
| private void updateHoverBehavior() { |
| SourceViewerConfiguration configuration = getSourceViewerConfiguration(); |
| String[] types = configuration.getConfiguredContentTypes(getSourceViewer()); |
| |
| for (int i = 0; i < types.length; i++) { |
| |
| String t = types[i]; |
| |
| ISourceViewer sourceViewer = getSourceViewer(); |
| if (sourceViewer instanceof ITextViewerExtension2) { |
| // Remove existing hovers |
| ((ITextViewerExtension2) sourceViewer).removeTextHovers(t); |
| |
| int[] stateMasks = configuration.getConfiguredTextHoverStateMasks(getSourceViewer(), t); |
| |
| if (stateMasks != null) { |
| for (int j = 0; j < stateMasks.length; j++) { |
| int stateMask = stateMasks[j]; |
| ITextHover textHover = configuration.getTextHover(sourceViewer, t, stateMask); |
| ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, stateMask); |
| } |
| } else { |
| ITextHover textHover = configuration.getTextHover(sourceViewer, t); |
| ((ITextViewerExtension2) sourceViewer).setTextHover( |
| textHover, |
| t, |
| ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK); |
| } |
| } else { |
| sourceViewer.setTextHover(configuration.getTextHover(sourceViewer, t), t); |
| } |
| } |
| } |
| |
| private void updateOutlinePageNew(Outline outline) { |
| if (fOutlinePage_NEW != null && outline != null) { |
| int offset = getSourceViewer().getSelectedRange().x; |
| fOutlinePage_NEW.setInput(outline, offset); |
| } |
| } |
| } |