| Index: editor/tools/plugins/com.google.dart.tools.ui/src/com/google/dart/tools/ui/internal/text/editor/DartEditor.java
|
| diff --git a/editor/tools/plugins/com.google.dart.tools.ui/src/com/google/dart/tools/ui/internal/text/editor/DartEditor.java b/editor/tools/plugins/com.google.dart.tools.ui/src/com/google/dart/tools/ui/internal/text/editor/DartEditor.java
|
| index c2de6103c30b5846927e9bf12fe17f866d792acd..309ca5c5f7756e8f1d87ed2f416783f77c4d0bfb 100644
|
| --- a/editor/tools/plugins/com.google.dart.tools.ui/src/com/google/dart/tools/ui/internal/text/editor/DartEditor.java
|
| +++ b/editor/tools/plugins/com.google.dart.tools.ui/src/com/google/dart/tools/ui/internal/text/editor/DartEditor.java
|
| @@ -28,6 +28,7 @@ import com.google.dart.tools.core.model.SourceReference;
|
| import com.google.dart.tools.core.utilities.ast.DartElementLocator;
|
| import com.google.dart.tools.core.utilities.ast.NameOccurrencesFinder;
|
| import com.google.dart.tools.core.utilities.compiler.DartCompilerUtilities;
|
| +import com.google.dart.tools.core.utilities.general.Timer;
|
| import com.google.dart.tools.ui.DartToolsPlugin;
|
| import com.google.dart.tools.ui.DartX;
|
| import com.google.dart.tools.ui.IContextMenuConstants;
|
| @@ -200,1274 +201,1274 @@ public abstract class DartEditor extends AbstractDecoratedTextEditor implements
|
| IViewPartInputProvider {
|
|
|
| /**
|
| - * Internal implementation class for a change listener.
|
| + * 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>
|
| */
|
| - protected abstract class AbstractSelectionChangedListener implements ISelectionChangedListener {
|
| + public static class EclipsePreferencesAdapter implements IPreferenceStore {
|
|
|
| /**
|
| - * 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
|
| + * Preference change listener. Listens for events preferences fires a
|
| + * {@link org.eclipse.jface.util.PropertyChangeEvent} on this adapter with arguments from the
|
| + * received event.
|
| */
|
| - public void install(ISelectionProvider selectionProvider) {
|
| - if (selectionProvider == null) {
|
| - return;
|
| - }
|
| + private class PreferenceChangeListener implements IEclipsePreferences.IPreferenceChangeListener {
|
|
|
| - if (selectionProvider instanceof IPostSelectionProvider) {
|
| - IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
|
| - provider.addPostSelectionChangedListener(this);
|
| - } else {
|
| - selectionProvider.addSelectionChangedListener(this);
|
| + /**
|
| + * {@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;
|
| +
|
| /**
|
| - * Removes this selection changed listener from the given selection provider.
|
| + * Initialize with the node to wrap
|
| *
|
| - * @param selectionProvider the selection provider
|
| + * @param context the context to access
|
| + * @param qualifier the qualifier
|
| */
|
| - public void uninstall(ISelectionProvider selectionProvider) {
|
| - if (selectionProvider == null) {
|
| - return;
|
| - }
|
| -
|
| - if (selectionProvider instanceof IPostSelectionProvider) {
|
| - IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
|
| - provider.removePostSelectionChangedListener(this);
|
| - } else {
|
| - selectionProvider.removeSelectionChangedListener(this);
|
| - }
|
| + public EclipsePreferencesAdapter(IScopeContext context, String qualifier) {
|
| + fContext = context;
|
| + fQualifier = qualifier;
|
| }
|
| - }
|
| -
|
| - /**
|
| - * Text operation action to delete the next sub-word.
|
| - */
|
| - protected class DeleteNextSubWordAction extends NextSubWordAction implements IUpdate {
|
|
|
| /**
|
| - * Creates a new delete next sub-word action.
|
| + * {@inheritDoc}
|
| */
|
| - public DeleteNextSubWordAction() {
|
| - super(ST.DELETE_WORD_NEXT);
|
| + @Override
|
| + public void addPropertyChangeListener(IPropertyChangeListener listener) {
|
| + if (fListeners.size() == 0) {
|
| + getNode().addPreferenceChangeListener(fListener);
|
| + }
|
| + fListeners.add(listener);
|
| }
|
|
|
| - /*
|
| - * @see org.eclipse.ui.texteditor.IUpdate#update()
|
| + /**
|
| + * {@inheritDoc}
|
| */
|
| @Override
|
| - public void update() {
|
| - setEnabled(isEditorInputModifiable());
|
| + public boolean contains(String name) {
|
| + return getNode().get(name, null) != null;
|
| }
|
|
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| @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
|
| - }
|
| + 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);
|
| }
|
| }
|
| - }
|
| -
|
| - /**
|
| - * Text operation action to delete the previous sub-word.
|
| - */
|
| - protected class DeletePreviousSubWordAction extends PreviousSubWordAction implements IUpdate {
|
|
|
| /**
|
| - * Creates a new delete previous sub-word action.
|
| + * {@inheritDoc}
|
| */
|
| - public DeletePreviousSubWordAction() {
|
| - super(ST.DELETE_WORD_PREVIOUS);
|
| + @Override
|
| + public boolean getBoolean(String name) {
|
| + return getNode().getBoolean(name, BOOLEAN_DEFAULT_DEFAULT);
|
| }
|
|
|
| - /*
|
| - * @see org.eclipse.ui.texteditor.IUpdate#update()
|
| + /**
|
| + * {@inheritDoc}
|
| */
|
| @Override
|
| - public void update() {
|
| - setEnabled(isEditorInputModifiable());
|
| + public boolean getDefaultBoolean(String name) {
|
| + return BOOLEAN_DEFAULT_DEFAULT;
|
| }
|
|
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| @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);
|
| + public double getDefaultDouble(String name) {
|
| + return DOUBLE_DEFAULT_DEFAULT;
|
| + }
|
|
|
| - 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;
|
| - }
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public float getDefaultFloat(String name) {
|
| + return FLOAT_DEFAULT_DEFAULT;
|
| + }
|
|
|
| - try {
|
| - viewer.getDocument().replace(position, length, ""); //$NON-NLS-1$
|
| - } catch (BadLocationException exception) {
|
| - // Should not happen
|
| - }
|
| - }
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public int getDefaultInt(String name) {
|
| + return INT_DEFAULT_DEFAULT;
|
| }
|
| - }
|
|
|
| - /**
|
| - * 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 {
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public long getDefaultLong(String name) {
|
| + return LONG_DEFAULT_DEFAULT;
|
| + }
|
|
|
| - /*
|
| - *
|
| + /**
|
| + * {@inheritDoc}
|
| */
|
| - FormatElementAction() {
|
| - setEnabled(isEditorInputModifiable());
|
| + @Override
|
| + public String getDefaultString(String name) {
|
| + return STRING_DEFAULT_DEFAULT;
|
| }
|
|
|
| - /*
|
| - * @see org.eclipse.jface.action.IAction#run()
|
| + /**
|
| + * {@inheritDoc}
|
| */
|
| @Override
|
| - public void run() {
|
| + public double getDouble(String name) {
|
| + return getNode().getDouble(name, DOUBLE_DEFAULT_DEFAULT);
|
| + }
|
|
|
| - final DartSourceViewer viewer = (DartSourceViewer) getSourceViewer();
|
| - if (viewer.isEditable()) {
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public float getFloat(String name) {
|
| + return getNode().getFloat(name, FLOAT_DEFAULT_DEFAULT);
|
| + }
|
|
|
| - final Point selection = viewer.rememberSelection();
|
| - try {
|
| - viewer.setRedraw(false);
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public int getInt(String name) {
|
| + return getNode().getInt(name, INT_DEFAULT_DEFAULT);
|
| + }
|
|
|
| - final String type = TextUtilities.getContentType(
|
| - viewer.getDocument(),
|
| - DartPartitions.DART_PARTITIONING,
|
| - selection.x,
|
| - true);
|
| - if (type.equals(IDocument.DEFAULT_CONTENT_TYPE) && selection.y == 0) {
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public long getLong(String name) {
|
| + return getNode().getLong(name, LONG_DEFAULT_DEFAULT);
|
| + }
|
|
|
| - try {
|
| - final DartElement element = getElementAt(selection.x, true);
|
| - if (element != null && element.exists()) {
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public String getString(String name) {
|
| + return getNode().get(name, STRING_DEFAULT_DEFAULT);
|
| + }
|
|
|
| - final int kind = element.getElementType();
|
| - if (kind == DartElement.TYPE || kind == DartElement.METHOD) {
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public boolean isDefault(String name) {
|
| + return false;
|
| + }
|
|
|
| - final SourceReference reference = (SourceReference) element;
|
| - final SourceRange range = reference.getSourceRange();
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public boolean needsSaving() {
|
| + try {
|
| + return getNode().keys().length > 0;
|
| + } catch (BackingStoreException e) {
|
| + // ignore
|
| + }
|
| + return true;
|
| + }
|
|
|
| - if (range != null) {
|
| - viewer.setSelectedRange(range.getOffset(), range.getLength());
|
| - viewer.doOperation(ISourceViewer.FORMAT);
|
| - }
|
| - }
|
| - }
|
| - } catch (DartModelException exception) {
|
| - // Should not happen
|
| - }
|
| - } else {
|
| - viewer.setSelectedRange(selection.x, 1);
|
| - viewer.doOperation(ISourceViewer.FORMAT);
|
| - }
|
| - } catch (BadLocationException exception) {
|
| - // Can not happen
|
| - } finally {
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public void putValue(String name, String value) {
|
| + throw new UnsupportedOperationException();
|
| + }
|
|
|
| - viewer.setRedraw(true);
|
| - viewer.restoreSelection();
|
| - }
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public void removePropertyChangeListener(IPropertyChangeListener listener) {
|
| + fListeners.remove(listener);
|
| + if (fListeners.size() == 0) {
|
| + getNode().removePreferenceChangeListener(fListener);
|
| }
|
| }
|
|
|
| - /*
|
| - * @see org.eclipse.ui.texteditor.IUpdate#update()
|
| + /**
|
| + * {@inheritDoc}
|
| */
|
| @Override
|
| - public void update() {
|
| - setEnabled(isEditorInputModifiable());
|
| + public void setDefault(String name, boolean value) {
|
| + throw new UnsupportedOperationException();
|
| }
|
| - }
|
|
|
| - /**
|
| - * Text navigation action to navigate to the next sub-word.
|
| - */
|
| - protected class NavigateNextSubWordAction extends NextSubWordAction {
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public void setDefault(String name, double value) {
|
| + throw new UnsupportedOperationException();
|
| + }
|
|
|
| /**
|
| - * Creates a new navigate next sub-word action.
|
| + * {@inheritDoc}
|
| */
|
| - public NavigateNextSubWordAction() {
|
| - super(ST.WORD_NEXT);
|
| + @Override
|
| + public void setDefault(String name, float value) {
|
| + throw new UnsupportedOperationException();
|
| }
|
|
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| @Override
|
| - protected void setCaretPosition(final int position) {
|
| - getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position));
|
| + public void setDefault(String name, int value) {
|
| + throw new UnsupportedOperationException();
|
| }
|
| - }
|
|
|
| - /**
|
| - * Text navigation action to navigate to the previous sub-word.
|
| - */
|
| - protected class NavigatePreviousSubWordAction extends PreviousSubWordAction {
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public void setDefault(String name, long value) {
|
| + throw new UnsupportedOperationException();
|
| + }
|
|
|
| /**
|
| - * Creates a new navigate previous sub-word action.
|
| + * {@inheritDoc}
|
| */
|
| - public NavigatePreviousSubWordAction() {
|
| - super(ST.WORD_PREVIOUS);
|
| + @Override
|
| + public void setDefault(String name, String defaultObject) {
|
| + throw new UnsupportedOperationException();
|
| }
|
|
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| @Override
|
| - protected void setCaretPosition(final int position) {
|
| - getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position));
|
| + public void setToDefault(String name) {
|
| + throw new UnsupportedOperationException();
|
| }
|
| - }
|
|
|
| - /**
|
| - * Text navigation action to navigate to the next sub-word.
|
| - */
|
| - protected abstract class NextSubWordAction extends TextNavigationAction {
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public void setValue(String name, boolean value) {
|
| + throw new UnsupportedOperationException();
|
| + }
|
|
|
| - protected DartWordIterator fIterator = new DartWordIterator();
|
| + /**
|
| + * {@inheritDoc}
|
| + */
|
| + @Override
|
| + public void setValue(String name, double value) {
|
| + throw new UnsupportedOperationException();
|
| + }
|
|
|
| /**
|
| - * 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.
|
| + * {@inheritDoc}
|
| */
|
| - protected NextSubWordAction(int code) {
|
| - super(getSourceViewer().getTextWidget(), code);
|
| + @Override
|
| + public void setValue(String name, float value) {
|
| + throw new UnsupportedOperationException();
|
| }
|
|
|
| - /*
|
| - * @see org.eclipse.jface.action.IAction#run()
|
| + /**
|
| + * {@inheritDoc}
|
| */
|
| @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;
|
| - }
|
| + public void setValue(String name, int value) {
|
| + throw new UnsupportedOperationException();
|
| + }
|
|
|
| - 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) {
|
| + /**
|
| + * {@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;
|
| }
|
|
|
| - 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
|
| + if (selectionProvider instanceof IPostSelectionProvider) {
|
| + IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
|
| + provider.addPostSelectionChangedListener(this);
|
| + } else {
|
| + selectionProvider.addSelectionChangedListener(this);
|
| }
|
| }
|
|
|
| /**
|
| - * Finds the next position after the given position.
|
| + * Removes this selection changed listener from the given selection provider.
|
| *
|
| - * @param position the current position
|
| - * @return the next position
|
| + * @param selectionProvider the selection provider
|
| */
|
| - 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);
|
| - }
|
| + public void uninstall(ISelectionProvider selectionProvider) {
|
| + if (selectionProvider == null) {
|
| + return;
|
| }
|
|
|
| - 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;
|
| - }
|
| - }
|
| - }
|
| + if (selectionProvider instanceof IPostSelectionProvider) {
|
| + IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
|
| + provider.removePostSelectionChangedListener(this);
|
| + } else {
|
| + selectionProvider.removeSelectionChangedListener(this);
|
| }
|
| -
|
| - 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.
|
| + * Text operation action to delete the next sub-word.
|
| */
|
| - protected abstract class PreviousSubWordAction extends TextNavigationAction {
|
| -
|
| - protected DartWordIterator fIterator = new DartWordIterator();
|
| + protected class DeleteNextSubWordAction extends NextSubWordAction implements IUpdate {
|
|
|
| /**
|
| - * 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.
|
| + * Creates a new delete next sub-word action.
|
| */
|
| - protected PreviousSubWordAction(final int code) {
|
| - super(getSourceViewer().getTextWidget(), code);
|
| + public DeleteNextSubWordAction() {
|
| + super(ST.DELETE_WORD_NEXT);
|
| }
|
|
|
| /*
|
| - * @see org.eclipse.jface.action.IAction#run()
|
| + * @see org.eclipse.ui.texteditor.IUpdate#update()
|
| */
|
| @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();
|
| + public void update() {
|
| + setEnabled(isEditorInputModifiable());
|
| + }
|
| +
|
| + @Override
|
| + protected void setCaretPosition(final int position) {
|
| + if (!validateEditorInputState()) {
|
| 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;
|
| - }
|
| + 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);
|
|
|
| - 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();
|
| + if (caret == widgetSelection.x) {
|
| + text.setSelectionRange(widgetSelection.y, offset - widgetSelection.y);
|
| + } else {
|
| + text.setSelectionRange(widgetSelection.x, offset - widgetSelection.x);
|
| }
|
| - } 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);
|
| + 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;
|
| }
|
| - }
|
|
|
| - 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;
|
| - }
|
| - }
|
| + try {
|
| + viewer.getDocument().replace(caret, length, ""); //$NON-NLS-1$
|
| + } catch (BadLocationException exception) {
|
| + // Should not happen
|
| }
|
| }
|
| -
|
| - 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.
|
| + * Text operation action to delete the previous sub-word.
|
| */
|
| - protected class SelectNextSubWordAction extends NextSubWordAction {
|
| + protected class DeletePreviousSubWordAction extends PreviousSubWordAction implements IUpdate {
|
|
|
| /**
|
| - * Creates a new select next sub-word action.
|
| + * Creates a new delete previous sub-word action.
|
| */
|
| - public SelectNextSubWordAction() {
|
| - super(ST.SELECT_WORD_NEXT);
|
| + public DeletePreviousSubWordAction() {
|
| + super(ST.DELETE_WORD_PREVIOUS);
|
| }
|
|
|
| + /*
|
| + * @see org.eclipse.ui.texteditor.IUpdate#update()
|
| + */
|
| @Override
|
| - protected void setCaretPosition(final int position) {
|
| - final ISourceViewer viewer = getSourceViewer();
|
| + public void update() {
|
| + setEnabled(isEditorInputModifiable());
|
| + }
|
|
|
| - final StyledText text = viewer.getTextWidget();
|
| - if (text != null && !text.isDisposed()) {
|
| + @Override
|
| + protected void setCaretPosition(int position) {
|
| + if (!validateEditorInputState()) {
|
| + return;
|
| + }
|
|
|
| - final Point selection = text.getSelection();
|
| + 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 == selection.x) {
|
| - text.setSelectionRange(selection.y, offset - selection.y);
|
| + if (caret == widgetSelection.x) {
|
| + text.setSelectionRange(widgetSelection.y, offset - widgetSelection.y);
|
| } else {
|
| - text.setSelectionRange(selection.x, offset - selection.x);
|
| + 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
|
| }
|
| }
|
| }
|
| }
|
|
|
| /**
|
| - * Text operation action to select the previous sub-word.
|
| + * 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 SelectPreviousSubWordAction extends PreviousSubWordAction {
|
| + protected class FormatElementAction extends Action implements IUpdate {
|
|
|
| - /**
|
| - * Creates a new select previous sub-word action.
|
| + /*
|
| + *
|
| */
|
| - public SelectPreviousSubWordAction() {
|
| - super(ST.SELECT_WORD_PREVIOUS);
|
| + FormatElementAction() {
|
| + setEnabled(isEditorInputModifiable());
|
| }
|
|
|
| + /*
|
| + * @see org.eclipse.jface.action.IAction#run()
|
| + */
|
| @Override
|
| - protected void setCaretPosition(final int position) {
|
| - final ISourceViewer viewer = getSourceViewer();
|
| + public void run() {
|
|
|
| - final StyledText text = viewer.getTextWidget();
|
| - if (text != null && !text.isDisposed()) {
|
| + final DartSourceViewer viewer = (DartSourceViewer) getSourceViewer();
|
| + if (viewer.isEditable()) {
|
|
|
| - final Point selection = text.getSelection();
|
| - final int caret = text.getCaretOffset();
|
| - final int offset = modelOffset2WidgetOffset(viewer, position);
|
| + final Point selection = viewer.rememberSelection();
|
| + try {
|
| + viewer.setRedraw(false);
|
|
|
| - if (caret == selection.x) {
|
| - text.setSelectionRange(selection.y, offset - selection.y);
|
| - } else {
|
| - text.setSelectionRange(selection.x, offset - selection.x);
|
| + final String type = TextUtilities.getContentType(
|
| + viewer.getDocument(),
|
| + DartPartitions.DART_PARTITIONING,
|
| + selection.x,
|
| + true);
|
| + if (type.equals(IDocument.DEFAULT_CONTENT_TYPE) && selection.y == 0) {
|
| +
|
| + try {
|
| + final DartElement element = getElementAt(selection.x, true);
|
| + if (element != null && element.exists()) {
|
| +
|
| + final int kind = element.getElementType();
|
| + if (kind == DartElement.TYPE || kind == DartElement.METHOD) {
|
| +
|
| + final SourceReference reference = (SourceReference) element;
|
| + final SourceRange range = reference.getSourceRange();
|
| +
|
| + if (range != null) {
|
| + viewer.setSelectedRange(range.getOffset(), range.getLength());
|
| + viewer.doOperation(ISourceViewer.FORMAT);
|
| + }
|
| + }
|
| + }
|
| + } catch (DartModelException exception) {
|
| + // Should not happen
|
| + }
|
| + } else {
|
| + viewer.setSelectedRange(selection.x, 1);
|
| + viewer.doOperation(ISourceViewer.FORMAT);
|
| + }
|
| + } catch (BadLocationException exception) {
|
| + // Can not happen
|
| + } finally {
|
| +
|
| + viewer.setRedraw(true);
|
| + viewer.restoreSelection();
|
| }
|
| }
|
| }
|
| +
|
| + /*
|
| + * @see org.eclipse.ui.texteditor.IUpdate#update()
|
| + */
|
| + @Override
|
| + public void update() {
|
| + setEnabled(isEditorInputModifiable());
|
| + }
|
| }
|
|
|
| /**
|
| - * 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.
|
| + * Text navigation action to navigate to the next sub-word.
|
| */
|
| - protected class SmartLineStartAction extends LineStartAction {
|
| + protected class NavigateNextSubWordAction extends NextSubWordAction {
|
|
|
| /**
|
| - * 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
|
| + * Creates a new navigate next sub-word action.
|
| */
|
| - public SmartLineStartAction(final StyledText textWidget, final boolean doSelect) {
|
| - super(textWidget, doSelect);
|
| + public NavigateNextSubWordAction() {
|
| + super(ST.WORD_NEXT);
|
| }
|
|
|
| - /*
|
| - * @see org.eclipse.ui.texteditor.AbstractTextEditor.LineStartAction#
|
| - * getLineStartPosition(java.lang.String, int, java.lang.String)
|
| - */
|
| @Override
|
| - protected int getLineStartPosition(final IDocument document, final String line,
|
| - final int length, final int offset) {
|
| + protected void setCaretPosition(final int position) {
|
| + getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position));
|
| + }
|
| + }
|
|
|
| - String type = IDocument.DEFAULT_CONTENT_TYPE;
|
| - try {
|
| - type = TextUtilities.getContentType(
|
| - document,
|
| - DartPartitions.DART_PARTITIONING,
|
| - offset,
|
| - true);
|
| - } catch (BadLocationException exception) {
|
| - // Should not happen
|
| - }
|
| + /**
|
| + * Text navigation action to navigate to the previous sub-word.
|
| + */
|
| + protected class NavigatePreviousSubWordAction extends PreviousSubWordAction {
|
|
|
| - 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;
|
| + /**
|
| + * 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));
|
| }
|
| }
|
|
|
| /**
|
| - * Finds and marks occurrence annotations.
|
| + * Text navigation action to navigate to the next sub-word.
|
| */
|
| - class OccurrencesFinderJob extends Job {
|
| -
|
| - private final IDocument fDocument;
|
| - private final ISelection fSelection;
|
| - private ISelectionValidator fPostSelectionValidator;
|
| - private boolean fCanceled = false;
|
| - private IProgressMonitor fProgressMonitor;
|
| - private final Position[] fPositions;
|
| + protected abstract class NextSubWordAction extends TextNavigationAction {
|
|
|
| - public OccurrencesFinderJob(IDocument document, Position[] positions, ISelection selection) {
|
| - super(DartEditorMessages.JavaEditor_markOccurrences_job_name);
|
| - fDocument = document;
|
| - fSelection = selection;
|
| - fPositions = positions;
|
| + protected DartWordIterator fIterator = new DartWordIterator();
|
|
|
| - if (getSelectionProvider() instanceof ISelectionValidator) {
|
| - fPostSelectionValidator = (ISelectionValidator) getSelectionProvider();
|
| - }
|
| + /**
|
| + * 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);
|
| }
|
|
|
| /*
|
| - * @see Job#run(org.eclipse.core.runtime.IProgressMonitor)
|
| + * @see org.eclipse.jface.action.IAction#run()
|
| */
|
| @Override
|
| - public IStatus run(IProgressMonitor progressMonitor) {
|
| -
|
| - fProgressMonitor = progressMonitor;
|
| -
|
| - if (isCanceled()) {
|
| - return Status.CANCEL_STATUS;
|
| + 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;
|
| }
|
|
|
| - ITextViewer textViewer = getViewer();
|
| - if (textViewer == null) {
|
| - return Status.CANCEL_STATUS;
|
| + 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;
|
| }
|
|
|
| - IDocument document = textViewer.getDocument();
|
| - if (document == null) {
|
| - return Status.CANCEL_STATUS;
|
| + 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
|
| }
|
| + }
|
|
|
| - IDocumentProvider documentProvider = getDocumentProvider();
|
| - if (documentProvider == null) {
|
| - return Status.CANCEL_STATUS;
|
| + /**
|
| + * 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);
|
| + }
|
| }
|
|
|
| - IAnnotationModel annotationModel = documentProvider.getAnnotationModel(getEditorInput());
|
| - if (annotationModel == null) {
|
| - return Status.CANCEL_STATUS;
|
| + 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;
|
| + }
|
| + }
|
| + }
|
| }
|
|
|
| - // Add occurrence annotations
|
| - int length = fPositions.length;
|
| - Map<Annotation, Position> annotationMap = new HashMap<Annotation, Position>(length);
|
| - for (int i = 0; i < length; i++) {
|
| + return next;
|
| + }
|
|
|
| - if (isCanceled()) {
|
| - return Status.CANCEL_STATUS;
|
| - }
|
| + /**
|
| + * 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);
|
| + }
|
|
|
| - String message;
|
| - Position position = fPositions[i];
|
| + /**
|
| + * Text navigation action to navigate to the previous sub-word.
|
| + */
|
| + protected abstract class PreviousSubWordAction extends TextNavigationAction {
|
|
|
| - // Create & add annotation
|
| - try {
|
| - message = document.get(position.offset, position.length);
|
| - } catch (BadLocationException ex) {
|
| - // Skip this match
|
| - continue;
|
| + 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);
|
| + }
|
| +
|
| + /*
|
| + * @see org.eclipse.jface.action.IAction#run()
|
| + */
|
| + @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();
|
| }
|
| - annotationMap.put(new Annotation("com.google.dart.tools.ui.occurrences", false, message), //$NON-NLS-1$
|
| - position);
|
| + } catch (BadLocationException x) {
|
| + // ignore - getLineOfOffset failed
|
| }
|
|
|
| - if (isCanceled()) {
|
| - return Status.CANCEL_STATUS;
|
| + }
|
| +
|
| + /**
|
| + * 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);
|
| + }
|
| }
|
|
|
| - synchronized (getLockObject(annotationModel)) {
|
| - if (annotationModel instanceof IAnnotationModelExtension) {
|
| - ((IAnnotationModelExtension) annotationModel).replaceAnnotations(
|
| - fOccurrenceAnnotations,
|
| - annotationMap);
|
| + 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 {
|
| - removeOccurrenceAnnotations();
|
| - Iterator<Map.Entry<Annotation, Position>> iter = annotationMap.entrySet().iterator();
|
| - while (iter.hasNext()) {
|
| - Map.Entry<Annotation, Position> mapEntry = iter.next();
|
| - annotationModel.addAnnotation(mapEntry.getKey(), mapEntry.getValue());
|
| + 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;
|
| + }
|
| }
|
| }
|
| - fOccurrenceAnnotations = annotationMap.keySet().toArray(
|
| - new Annotation[annotationMap.keySet().size()]);
|
| }
|
|
|
| - return Status.OK_STATUS;
|
| - }
|
| -
|
| - // cannot use cancel() because it is declared final
|
| - void doCancel() {
|
| - fCanceled = true;
|
| - cancel();
|
| + return previous;
|
| }
|
|
|
| - private boolean isCanceled() {
|
| - return fCanceled
|
| - || fProgressMonitor.isCanceled()
|
| - || fPostSelectionValidator != null
|
| - && !(fPostSelectionValidator.isValid(fSelection) || fForcedMarkOccurrencesSelection == fSelection)
|
| - || LinkedModeModel.hasInstalledModel(fDocument);
|
| - }
|
| + /**
|
| + * 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);
|
| }
|
|
|
| /**
|
| - * Cancels the occurrences finder job upon document changes.
|
| + * Text operation action to select the next sub-word.
|
| */
|
| - class OccurrencesFinderJobCanceler implements IDocumentListener, ITextInputListener {
|
| + protected class SelectNextSubWordAction extends NextSubWordAction {
|
|
|
| - /*
|
| - * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org
|
| - * .eclipse.jface.text.DocumentEvent)
|
| + /**
|
| + * Creates a new select next sub-word action.
|
| */
|
| - @Override
|
| - public void documentAboutToBeChanged(DocumentEvent event) {
|
| - if (fOccurrencesFinderJob != null) {
|
| - fOccurrencesFinderJob.doCancel();
|
| - }
|
| + public SelectNextSubWordAction() {
|
| + super(ST.SELECT_WORD_NEXT);
|
| }
|
|
|
| - /*
|
| - * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.
|
| - * jface.text.DocumentEvent)
|
| - */
|
| @Override
|
| - public void documentChanged(DocumentEvent event) {
|
| - }
|
| + protected void setCaretPosition(final int position) {
|
| + final ISourceViewer viewer = getSourceViewer();
|
|
|
| - /*
|
| - * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged
|
| - * (org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
|
| - */
|
| - @Override
|
| - public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
|
| - if (oldInput == null) {
|
| - return;
|
| - }
|
| + final StyledText text = viewer.getTextWidget();
|
| + if (text != null && !text.isDisposed()) {
|
|
|
| - oldInput.removeDocumentListener(this);
|
| - }
|
| + final Point selection = text.getSelection();
|
| + final int caret = text.getCaretOffset();
|
| + final int offset = modelOffset2WidgetOffset(viewer, position);
|
|
|
| - /*
|
| - * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse
|
| - * .jface.text.IDocument, org.eclipse.jface.text.IDocument)
|
| - */
|
| - @Override
|
| - public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
|
| - if (newInput == null) {
|
| - return;
|
| + if (caret == selection.x) {
|
| + text.setSelectionRange(selection.y, offset - selection.y);
|
| + } else {
|
| + text.setSelectionRange(selection.x, offset - selection.x);
|
| + }
|
| }
|
| - newInput.addDocumentListener(this);
|
| }
|
| + }
|
|
|
| - public void install() {
|
| - ISourceViewer sourceViewer = getSourceViewer();
|
| - if (sourceViewer == null) {
|
| - return;
|
| - }
|
| + /**
|
| + * Text operation action to select the previous sub-word.
|
| + */
|
| + protected class SelectPreviousSubWordAction extends PreviousSubWordAction {
|
|
|
| - StyledText text = sourceViewer.getTextWidget();
|
| - if (text == null || text.isDisposed()) {
|
| - return;
|
| - }
|
| + /**
|
| + * Creates a new select previous sub-word action.
|
| + */
|
| + public SelectPreviousSubWordAction() {
|
| + super(ST.SELECT_WORD_PREVIOUS);
|
| + }
|
|
|
| - sourceViewer.addTextInputListener(this);
|
| + @Override
|
| + protected void setCaretPosition(final int position) {
|
| + final ISourceViewer viewer = getSourceViewer();
|
|
|
| - IDocument document = sourceViewer.getDocument();
|
| - if (document != null) {
|
| - document.addDocumentListener(this);
|
| - }
|
| - }
|
| + final StyledText text = viewer.getTextWidget();
|
| + if (text != null && !text.isDisposed()) {
|
|
|
| - public void uninstall() {
|
| - ISourceViewer sourceViewer = getSourceViewer();
|
| - if (sourceViewer != null) {
|
| - sourceViewer.removeTextInputListener(this);
|
| - }
|
| + final Point selection = text.getSelection();
|
| + final int caret = text.getCaretOffset();
|
| + final int offset = modelOffset2WidgetOffset(viewer, position);
|
|
|
| - IDocumentProvider documentProvider = getDocumentProvider();
|
| - if (documentProvider != null) {
|
| - IDocument document = documentProvider.getDocument(getEditorInput());
|
| - if (document != null) {
|
| - document.removeDocumentListener(this);
|
| + if (caret == selection.x) {
|
| + text.setSelectionRange(selection.y, offset - selection.y);
|
| + } else {
|
| + text.setSelectionRange(selection.x, offset - selection.x);
|
| }
|
| }
|
| }
|
| }
|
|
|
| /**
|
| - * Internal activation listener.
|
| + * 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.
|
| */
|
| - private class ActivationListener implements IWindowListener {
|
| + 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);
|
| + }
|
|
|
| /*
|
| - * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui. IWorkbenchWindow)
|
| + * @see org.eclipse.ui.texteditor.AbstractTextEditor.LineStartAction#
|
| + * getLineStartPosition(java.lang.String, int, java.lang.String)
|
| */
|
| @Override
|
| - public void windowActivated(IWorkbenchWindow window) {
|
| - if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations
|
| - && isActivePart()) {
|
| - fForcedMarkOccurrencesSelection = getSelectionProvider().getSelection();
|
| - try {
|
| - DartElement input = getInputDartElement();
|
| - if (input != null) {
|
| - updateOccurrenceAnnotations(
|
| - (ITextSelection) fForcedMarkOccurrencesSelection,
|
| - DartToolsPlugin.getDefault().getASTProvider().getAST(
|
| - input,
|
| - ASTProvider.WAIT_NO,
|
| - getProgressMonitor()));
|
| - }
|
| - } catch (Exception ex) {
|
| - // ignore it
|
| - }
|
| - }
|
| - }
|
| -
|
| - /*
|
| - * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow )
|
| - */
|
| - @Override
|
| - public void windowClosed(IWorkbenchWindow window) {
|
| - }
|
| -
|
| - /*
|
| - * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui. IWorkbenchWindow)
|
| - */
|
| - @Override
|
| - public void windowDeactivated(IWorkbenchWindow window) {
|
| - if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations
|
| - && isActivePart()) {
|
| - removeOccurrenceAnnotations();
|
| - }
|
| - }
|
| -
|
| - /*
|
| - * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow )
|
| - */
|
| - @Override
|
| - public void windowOpened(IWorkbenchWindow window) {
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Instances of the class <code>ASTCache</code> maintain an AST structure corresponding to the
|
| - * contents of an editor's document.
|
| - */
|
| - private static class ASTCache {
|
| - /**
|
| - * The time at which the cache was last cleared.
|
| - */
|
| - private long clearTime;
|
| -
|
| - /**
|
| - * The AST corresponding to the contents of the editor's document, or <code>null</code> if the
|
| - * AST structure has not been accessed since the last time the cache was cleared.
|
| - */
|
| - private SoftReference<DartUnit> cachedAST;
|
| -
|
| - /**
|
| - * Initialize a newly created class to be empty.
|
| - */
|
| - public ASTCache() {
|
| - clearTime = 0L;
|
| - cachedAST = null;
|
| - }
|
| + protected int getLineStartPosition(final IDocument document, final String line,
|
| + final int length, final int offset) {
|
|
|
| - /**
|
| - * Clear the contents of this cache.
|
| - */
|
| - public void clear() {
|
| - synchronized (this) {
|
| - clearTime = System.nanoTime();
|
| - cachedAST = null;
|
| + String type = IDocument.DEFAULT_CONTENT_TYPE;
|
| + try {
|
| + type = TextUtilities.getContentType(
|
| + document,
|
| + DartPartitions.DART_PARTITIONING,
|
| + offset,
|
| + true);
|
| + } catch (BadLocationException exception) {
|
| + // Should not happen
|
| }
|
| - }
|
|
|
| - /**
|
| - * Return the AST structure held in this cache, or <code>null</code> if the AST structure needs
|
| - * to be created.
|
| - *
|
| - * @return the AST structure held in this cache
|
| - */
|
| - public DartUnit getAST() {
|
| - synchronized (this) {
|
| - if (cachedAST != null) {
|
| - return cachedAST.get();
|
| + 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)));
|
| }
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - /**
|
| - * Set the AST structure held in this cache to the given AST structure provided that the cache
|
| - * has not been cleared since the time at which the AST structure was created.
|
| - *
|
| - * @param creationTime the time at which the AST structure was created (in nanoseconds)
|
| - * @param ast the AST structure that is to be cached
|
| - */
|
| - public void setAST(long creationTime, DartUnit ast) {
|
| - synchronized (this) {
|
| - if (creationTime > clearTime) {
|
| - cachedAST = new SoftReference<DartUnit>(ast);
|
| + } 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;
|
| }
|
| }
|
|
|
| /**
|
| - * 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>
|
| + * Finds and marks occurrence annotations.
|
| */
|
| - private 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();
|
| + class OccurrencesFinderJob extends Job {
|
|
|
| - /** wrapped node */
|
| - private final IScopeContext fContext;
|
| - private final String fQualifier;
|
| + private final IDocument fDocument;
|
| + private final ISelection fSelection;
|
| + private ISelectionValidator fPostSelectionValidator;
|
| + private boolean fCanceled = false;
|
| + private IProgressMonitor fProgressMonitor;
|
| + private final Position[] fPositions;
|
|
|
| - /**
|
| - * 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;
|
| - }
|
| + public OccurrencesFinderJob(IDocument document, Position[] positions, ISelection selection) {
|
| + super(DartEditorMessages.JavaEditor_markOccurrences_job_name);
|
| + fDocument = document;
|
| + fSelection = selection;
|
| + fPositions = positions;
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public void addPropertyChangeListener(IPropertyChangeListener listener) {
|
| - if (fListeners.size() == 0) {
|
| - getNode().addPreferenceChangeListener(fListener);
|
| + if (getSelectionProvider() instanceof ISelectionValidator) {
|
| + fPostSelectionValidator = (ISelectionValidator) getSelectionProvider();
|
| }
|
| - fListeners.add(listener);
|
| }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| + /*
|
| + * @see Job#run(org.eclipse.core.runtime.IProgressMonitor)
|
| */
|
| @Override
|
| - public boolean contains(String name) {
|
| - return getNode().get(name, null) != null;
|
| - }
|
| + public IStatus run(IProgressMonitor progressMonitor) {
|
|
|
| - /**
|
| - * {@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);
|
| - }
|
| - }
|
| + fProgressMonitor = progressMonitor;
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public boolean getBoolean(String name) {
|
| - return getNode().getBoolean(name, BOOLEAN_DEFAULT_DEFAULT);
|
| - }
|
| + if (isCanceled()) {
|
| + return Status.CANCEL_STATUS;
|
| + }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public boolean getDefaultBoolean(String name) {
|
| - return BOOLEAN_DEFAULT_DEFAULT;
|
| - }
|
| + ITextViewer textViewer = getViewer();
|
| + if (textViewer == null) {
|
| + return Status.CANCEL_STATUS;
|
| + }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public double getDefaultDouble(String name) {
|
| - return DOUBLE_DEFAULT_DEFAULT;
|
| - }
|
| + IDocument document = textViewer.getDocument();
|
| + if (document == null) {
|
| + return Status.CANCEL_STATUS;
|
| + }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public float getDefaultFloat(String name) {
|
| - return FLOAT_DEFAULT_DEFAULT;
|
| - }
|
| + IDocumentProvider documentProvider = getDocumentProvider();
|
| + if (documentProvider == null) {
|
| + return Status.CANCEL_STATUS;
|
| + }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public int getDefaultInt(String name) {
|
| - return INT_DEFAULT_DEFAULT;
|
| - }
|
| + IAnnotationModel annotationModel = documentProvider.getAnnotationModel(getEditorInput());
|
| + if (annotationModel == null) {
|
| + return Status.CANCEL_STATUS;
|
| + }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public long getDefaultLong(String name) {
|
| - return LONG_DEFAULT_DEFAULT;
|
| - }
|
| + // Add occurrence annotations
|
| + int length = fPositions.length;
|
| + Map<Annotation, Position> annotationMap = new HashMap<Annotation, Position>(length);
|
| + for (int i = 0; i < length; i++) {
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public String getDefaultString(String name) {
|
| - return STRING_DEFAULT_DEFAULT;
|
| - }
|
| + if (isCanceled()) {
|
| + return Status.CANCEL_STATUS;
|
| + }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public double getDouble(String name) {
|
| - return getNode().getDouble(name, DOUBLE_DEFAULT_DEFAULT);
|
| - }
|
| + String message;
|
| + Position position = fPositions[i];
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public float getFloat(String name) {
|
| - return getNode().getFloat(name, FLOAT_DEFAULT_DEFAULT);
|
| - }
|
| + // Create & add annotation
|
| + try {
|
| + message = document.get(position.offset, position.length);
|
| + } catch (BadLocationException ex) {
|
| + // Skip this match
|
| + continue;
|
| + }
|
| + annotationMap.put(new Annotation("com.google.dart.tools.ui.occurrences", false, message), //$NON-NLS-1$
|
| + position);
|
| + }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public int getInt(String name) {
|
| - return getNode().getInt(name, INT_DEFAULT_DEFAULT);
|
| - }
|
| + if (isCanceled()) {
|
| + return Status.CANCEL_STATUS;
|
| + }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public long getLong(String name) {
|
| - return getNode().getLong(name, LONG_DEFAULT_DEFAULT);
|
| + synchronized (getLockObject(annotationModel)) {
|
| + if (annotationModel instanceof IAnnotationModelExtension) {
|
| + ((IAnnotationModelExtension) annotationModel).replaceAnnotations(
|
| + fOccurrenceAnnotations,
|
| + annotationMap);
|
| + } else {
|
| + removeOccurrenceAnnotations();
|
| + Iterator<Map.Entry<Annotation, Position>> iter = annotationMap.entrySet().iterator();
|
| + while (iter.hasNext()) {
|
| + Map.Entry<Annotation, Position> mapEntry = iter.next();
|
| + annotationModel.addAnnotation(mapEntry.getKey(), mapEntry.getValue());
|
| + }
|
| + }
|
| + fOccurrenceAnnotations = annotationMap.keySet().toArray(
|
| + new Annotation[annotationMap.keySet().size()]);
|
| + }
|
| +
|
| + return Status.OK_STATUS;
|
| }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public String getString(String name) {
|
| - return getNode().get(name, STRING_DEFAULT_DEFAULT);
|
| + // cannot use cancel() because it is declared final
|
| + void doCancel() {
|
| + fCanceled = true;
|
| + cancel();
|
| }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public boolean isDefault(String name) {
|
| - return false;
|
| + private boolean isCanceled() {
|
| + return fCanceled
|
| + || fProgressMonitor.isCanceled()
|
| + || fPostSelectionValidator != null
|
| + && !(fPostSelectionValidator.isValid(fSelection) || fForcedMarkOccurrencesSelection == fSelection)
|
| + || LinkedModeModel.hasInstalledModel(fDocument);
|
| }
|
| + }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| + /**
|
| + * Cancels the occurrences finder job upon document changes.
|
| + */
|
| + class OccurrencesFinderJobCanceler implements IDocumentListener, ITextInputListener {
|
| +
|
| + /*
|
| + * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org
|
| + * .eclipse.jface.text.DocumentEvent)
|
| */
|
| @Override
|
| - public boolean needsSaving() {
|
| - try {
|
| - return getNode().keys().length > 0;
|
| - } catch (BackingStoreException e) {
|
| - // ignore
|
| + public void documentAboutToBeChanged(DocumentEvent event) {
|
| + if (fOccurrencesFinderJob != null) {
|
| + fOccurrencesFinderJob.doCancel();
|
| }
|
| - return true;
|
| }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| + /*
|
| + * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.
|
| + * jface.text.DocumentEvent)
|
| */
|
| @Override
|
| - public void putValue(String name, String value) {
|
| - throw new UnsupportedOperationException();
|
| + public void documentChanged(DocumentEvent event) {
|
| }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| + /*
|
| + * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged
|
| + * (org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
|
| */
|
| @Override
|
| - public void removePropertyChangeListener(IPropertyChangeListener listener) {
|
| - fListeners.remove(listener);
|
| - if (fListeners.size() == 0) {
|
| - getNode().removePreferenceChangeListener(fListener);
|
| + public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
|
| + if (oldInput == null) {
|
| + return;
|
| }
|
| +
|
| + oldInput.removeDocumentListener(this);
|
| }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| + /*
|
| + * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse
|
| + * .jface.text.IDocument, org.eclipse.jface.text.IDocument)
|
| */
|
| @Override
|
| - public void setDefault(String name, boolean value) {
|
| - throw new UnsupportedOperationException();
|
| + public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
|
| + if (newInput == null) {
|
| + return;
|
| + }
|
| + newInput.addDocumentListener(this);
|
| }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public void setDefault(String name, double value) {
|
| - throw new UnsupportedOperationException();
|
| + public void install() {
|
| + ISourceViewer sourceViewer = getSourceViewer();
|
| + if (sourceViewer == null) {
|
| + return;
|
| + }
|
| +
|
| + StyledText text = sourceViewer.getTextWidget();
|
| + if (text == null || text.isDisposed()) {
|
| + return;
|
| + }
|
| +
|
| + sourceViewer.addTextInputListener(this);
|
| +
|
| + IDocument document = sourceViewer.getDocument();
|
| + if (document != null) {
|
| + document.addDocumentListener(this);
|
| + }
|
| }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| - */
|
| - @Override
|
| - public void setDefault(String name, float value) {
|
| - throw new UnsupportedOperationException();
|
| + public void uninstall() {
|
| + ISourceViewer sourceViewer = getSourceViewer();
|
| + if (sourceViewer != null) {
|
| + sourceViewer.removeTextInputListener(this);
|
| + }
|
| +
|
| + IDocumentProvider documentProvider = getDocumentProvider();
|
| + if (documentProvider != null) {
|
| + IDocument document = documentProvider.getDocument(getEditorInput());
|
| + if (document != null) {
|
| + document.removeDocumentListener(this);
|
| + }
|
| + }
|
| }
|
| + }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| + /**
|
| + * Internal activation listener.
|
| + */
|
| + private class ActivationListener implements IWindowListener {
|
| +
|
| + /*
|
| + * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui. IWorkbenchWindow)
|
| */
|
| @Override
|
| - public void setDefault(String name, int value) {
|
| - throw new UnsupportedOperationException();
|
| + public void windowActivated(IWorkbenchWindow window) {
|
| + if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations
|
| + && isActivePart()) {
|
| + fForcedMarkOccurrencesSelection = getSelectionProvider().getSelection();
|
| + try {
|
| + DartElement input = getInputDartElement();
|
| + if (input != null) {
|
| + updateOccurrenceAnnotations(
|
| + (ITextSelection) fForcedMarkOccurrencesSelection,
|
| + DartToolsPlugin.getDefault().getASTProvider().getAST(
|
| + input,
|
| + ASTProvider.WAIT_NO,
|
| + getProgressMonitor()));
|
| + }
|
| + } catch (Exception ex) {
|
| + // ignore it
|
| + }
|
| + }
|
| }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| + /*
|
| + * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow )
|
| */
|
| @Override
|
| - public void setDefault(String name, long value) {
|
| - throw new UnsupportedOperationException();
|
| + public void windowClosed(IWorkbenchWindow window) {
|
| }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| + /*
|
| + * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui. IWorkbenchWindow)
|
| */
|
| @Override
|
| - public void setDefault(String name, String defaultObject) {
|
| - throw new UnsupportedOperationException();
|
| + public void windowDeactivated(IWorkbenchWindow window) {
|
| + if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations
|
| + && isActivePart()) {
|
| + removeOccurrenceAnnotations();
|
| + }
|
| }
|
|
|
| - /**
|
| - * {@inheritDoc}
|
| + /*
|
| + * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow )
|
| */
|
| @Override
|
| - public void setToDefault(String name) {
|
| - throw new UnsupportedOperationException();
|
| + public void windowOpened(IWorkbenchWindow window) {
|
| }
|
| + }
|
|
|
| + /**
|
| + * Instances of the class <code>ASTCache</code> maintain an AST structure corresponding to the
|
| + * contents of an editor's document.
|
| + */
|
| + private static class ASTCache {
|
| /**
|
| - * {@inheritDoc}
|
| + * The time at which the cache was last cleared.
|
| */
|
| - @Override
|
| - public void setValue(String name, boolean value) {
|
| - throw new UnsupportedOperationException();
|
| - }
|
| + private long clearTime;
|
|
|
| /**
|
| - * {@inheritDoc}
|
| + * The AST corresponding to the contents of the editor's document, or <code>null</code> if the
|
| + * AST structure has not been accessed since the last time the cache was cleared.
|
| */
|
| - @Override
|
| - public void setValue(String name, double value) {
|
| - throw new UnsupportedOperationException();
|
| - }
|
| + private SoftReference<DartUnit> cachedAST;
|
|
|
| /**
|
| - * {@inheritDoc}
|
| + * Initialize a newly created class to be empty.
|
| */
|
| - @Override
|
| - public void setValue(String name, float value) {
|
| - throw new UnsupportedOperationException();
|
| + public ASTCache() {
|
| + clearTime = 0L;
|
| + cachedAST = null;
|
| }
|
|
|
| /**
|
| - * {@inheritDoc}
|
| + * Clear the contents of this cache.
|
| */
|
| - @Override
|
| - public void setValue(String name, int value) {
|
| - throw new UnsupportedOperationException();
|
| + public void clear() {
|
| + synchronized (this) {
|
| + clearTime = System.nanoTime();
|
| + cachedAST = null;
|
| + }
|
| }
|
|
|
| /**
|
| - * {@inheritDoc}
|
| + * Return the AST structure held in this cache, or <code>null</code> if the AST structure needs
|
| + * to be created.
|
| + *
|
| + * @return the AST structure held in this cache
|
| */
|
| - @Override
|
| - public void setValue(String name, long value) {
|
| - throw new UnsupportedOperationException();
|
| + public DartUnit getAST() {
|
| + synchronized (this) {
|
| + if (cachedAST != null) {
|
| + return cachedAST.get();
|
| + }
|
| + }
|
| + return null;
|
| }
|
|
|
| /**
|
| - * {@inheritDoc}
|
| + * Set the AST structure held in this cache to the given AST structure provided that the cache
|
| + * has not been cleared since the time at which the AST structure was created.
|
| + *
|
| + * @param creationTime the time at which the AST structure was created (in nanoseconds)
|
| + * @param ast the AST structure that is to be cached
|
| */
|
| - @Override
|
| - public void setValue(String name, String value) {
|
| - throw new UnsupportedOperationException();
|
| - }
|
| -
|
| - private IEclipsePreferences getNode() {
|
| - return fContext.getNode(fQualifier);
|
| + public void setAST(long creationTime, DartUnit ast) {
|
| + synchronized (this) {
|
| + if (creationTime > clearTime) {
|
| + cachedAST = new SoftReference<DartUnit>(ast);
|
| + }
|
| + }
|
| }
|
| -
|
| }
|
|
|
| /**
|
| @@ -2255,6 +2256,12 @@ public abstract class DartEditor extends AbstractDecoratedTextEditor implements
|
| }
|
| }
|
|
|
| + public void setPreferences(IPreferenceStore store) {
|
| + uninstallSemanticHighlighting();
|
| + super.setPreferenceStore(store);
|
| + installSemanticHighlighting();
|
| + }
|
| +
|
| public void setSelection(DartElement element) {
|
|
|
| if (element == null || element instanceof CompilationUnit) {
|
| @@ -3427,8 +3434,12 @@ public abstract class DartEditor extends AbstractDecoratedTextEditor implements
|
|
|
| @Override
|
| protected void performSave(boolean overwrite, IProgressMonitor progressMonitor) {
|
| + Timer timer = new Timer("save");
|
| +
|
| performSaveActions();
|
| super.performSave(overwrite, progressMonitor);
|
| +
|
| + timer.stop();
|
| }
|
|
|
| @Override
|
|
|