0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.ui.texteditor;
0011:
0012: import java.io.File;
0013: import java.util.Iterator;
0014: import java.util.List;
0015:
0016: import com.ibm.icu.text.MessageFormat;
0017:
0018: import org.eclipse.osgi.util.NLS;
0019:
0020: import org.eclipse.swt.SWT;
0021: import org.eclipse.swt.graphics.Color;
0022: import org.eclipse.swt.layout.GridData;
0023: import org.eclipse.swt.layout.GridLayout;
0024: import org.eclipse.swt.widgets.Composite;
0025: import org.eclipse.swt.widgets.Control;
0026: import org.eclipse.swt.widgets.Display;
0027: import org.eclipse.swt.widgets.FileDialog;
0028: import org.eclipse.swt.widgets.Shell;
0029:
0030: import org.eclipse.core.commands.operations.IOperationApprover;
0031: import org.eclipse.core.commands.operations.IUndoContext;
0032: import org.eclipse.core.filesystem.EFS;
0033: import org.eclipse.core.filesystem.IFileStore;
0034: import org.eclipse.core.filesystem.URIUtil;
0035:
0036: import org.eclipse.core.runtime.CoreException;
0037: import org.eclipse.core.runtime.IPath;
0038: import org.eclipse.core.runtime.IProgressMonitor;
0039: import org.eclipse.core.runtime.IStatus;
0040:
0041: import org.eclipse.core.resources.IFile;
0042: import org.eclipse.core.resources.IMarker;
0043: import org.eclipse.core.resources.IResource;
0044: import org.eclipse.core.resources.IResourceStatus;
0045: import org.eclipse.core.resources.IWorkspace;
0046: import org.eclipse.core.resources.IWorkspaceRoot;
0047: import org.eclipse.core.resources.ResourcesPlugin;
0048:
0049: import org.eclipse.core.filebuffers.FileBuffers;
0050: import org.eclipse.core.filebuffers.IFileBufferStatusCodes;
0051:
0052: import org.eclipse.jface.action.Action;
0053: import org.eclipse.jface.action.GroupMarker;
0054: import org.eclipse.jface.action.IAction;
0055: import org.eclipse.jface.action.IMenuManager;
0056: import org.eclipse.jface.action.MenuManager;
0057: import org.eclipse.jface.action.Separator;
0058: import org.eclipse.jface.dialogs.IDialogConstants;
0059: import org.eclipse.jface.dialogs.IMessageProvider;
0060: import org.eclipse.jface.dialogs.MessageDialog;
0061: import org.eclipse.jface.dialogs.MessageDialogWithToggle;
0062: import org.eclipse.jface.preference.IPreferenceStore;
0063: import org.eclipse.jface.util.PropertyChangeEvent;
0064: import org.eclipse.jface.viewers.ISelection;
0065: import org.eclipse.jface.viewers.ISelectionProvider;
0066: import org.eclipse.jface.window.Window;
0067:
0068: import org.eclipse.jface.text.BadLocationException;
0069: import org.eclipse.jface.text.IDocument;
0070: import org.eclipse.jface.text.ITextViewerExtension6;
0071: import org.eclipse.jface.text.Position;
0072: import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
0073: import org.eclipse.jface.text.revisions.IRevisionRulerColumn;
0074: import org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension;
0075: import org.eclipse.jface.text.revisions.RevisionInformation;
0076: import org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension.RenderingMode;
0077: import org.eclipse.jface.text.source.Annotation;
0078: import org.eclipse.jface.text.source.AnnotationRulerColumn;
0079: import org.eclipse.jface.text.source.ChangeRulerColumn;
0080: import org.eclipse.jface.text.source.CompositeRuler;
0081: import org.eclipse.jface.text.source.IAnnotationAccess;
0082: import org.eclipse.jface.text.source.IAnnotationAccessExtension2;
0083: import org.eclipse.jface.text.source.IAnnotationModel;
0084: import org.eclipse.jface.text.source.IChangeRulerColumn;
0085: import org.eclipse.jface.text.source.IOverviewRuler;
0086: import org.eclipse.jface.text.source.ISharedTextColors;
0087: import org.eclipse.jface.text.source.ISourceViewer;
0088: import org.eclipse.jface.text.source.ISourceViewerExtension;
0089: import org.eclipse.jface.text.source.ISourceViewerExtension3;
0090: import org.eclipse.jface.text.source.IVerticalRuler;
0091: import org.eclipse.jface.text.source.IVerticalRulerColumn;
0092: import org.eclipse.jface.text.source.LineChangeHover;
0093: import org.eclipse.jface.text.source.LineNumberChangeRulerColumn;
0094: import org.eclipse.jface.text.source.LineNumberRulerColumn;
0095: import org.eclipse.jface.text.source.OverviewRuler;
0096: import org.eclipse.jface.text.source.SourceViewer;
0097:
0098: import org.eclipse.ui.editors.text.DefaultEncodingSupport;
0099: import org.eclipse.ui.editors.text.EditorsUI;
0100: import org.eclipse.ui.editors.text.ForwardingDocumentProvider;
0101: import org.eclipse.ui.editors.text.IEncodingSupport;
0102: import org.eclipse.ui.editors.text.ITextEditorHelpContextIds;
0103:
0104: import org.eclipse.ui.IEditorInput;
0105: import org.eclipse.ui.IFileEditorInput;
0106: import org.eclipse.ui.IURIEditorInput;
0107: import org.eclipse.ui.IWorkbenchActionConstants;
0108: import org.eclipse.ui.IWorkbenchPage;
0109: import org.eclipse.ui.PlatformUI;
0110: import org.eclipse.ui.actions.ContributionItemFactory;
0111: import org.eclipse.ui.dialogs.PreferencesUtil;
0112: import org.eclipse.ui.dialogs.SaveAsDialog;
0113: import org.eclipse.ui.ide.FileStoreEditorInput;
0114: import org.eclipse.ui.ide.IDEActionFactory;
0115: import org.eclipse.ui.ide.IGotoMarker;
0116: import org.eclipse.ui.internal.editors.quickdiff.CompositeRevertAction;
0117: import org.eclipse.ui.internal.editors.quickdiff.RestoreAction;
0118: import org.eclipse.ui.internal.editors.quickdiff.RevertBlockAction;
0119: import org.eclipse.ui.internal.editors.quickdiff.RevertLineAction;
0120: import org.eclipse.ui.internal.editors.quickdiff.RevertSelectionAction;
0121: import org.eclipse.ui.internal.editors.text.EditorsPlugin;
0122: import org.eclipse.ui.internal.editors.text.NLSUtility;
0123: import org.eclipse.ui.internal.editors.text.RefreshEditorAction;
0124: import org.eclipse.ui.internal.texteditor.AnnotationColumn;
0125: import org.eclipse.ui.internal.texteditor.BooleanPreferenceToggleAction;
0126: import org.eclipse.ui.internal.texteditor.LineNumberColumn;
0127: import org.eclipse.ui.internal.texteditor.TextChangeHover;
0128: import org.eclipse.ui.keys.IBindingService;
0129: import org.eclipse.ui.operations.NonLocalUndoUserApprover;
0130: import org.eclipse.ui.part.FileEditorInput;
0131: import org.eclipse.ui.part.IShowInSource;
0132: import org.eclipse.ui.part.ShowInContext;
0133: import org.eclipse.ui.texteditor.rulers.IColumnSupport;
0134: import org.eclipse.ui.texteditor.rulers.IContributedRulerColumn;
0135: import org.eclipse.ui.texteditor.rulers.RulerColumnDescriptor;
0136: import org.eclipse.ui.texteditor.rulers.RulerColumnPreferenceAdapter;
0137: import org.eclipse.ui.texteditor.rulers.RulerColumnRegistry;
0138: import org.eclipse.ui.views.markers.MarkerViewUtil;
0139:
0140: /**
0141: * An intermediate editor comprising functionality not present in the leaner <code>AbstractTextEditor</code>,
0142: * but used in many heavy weight (and especially source editing) editors, such as line numbers,
0143: * change ruler, overview ruler, print margins, current line highlighting, etc.
0144: *
0145: * @since 3.0
0146: */
0147: public abstract class AbstractDecoratedTextEditor extends
0148: StatusTextEditor {
0149:
0150: /**
0151: * Preference key for showing the line number ruler.
0152: */
0153: private final static String LINE_NUMBER_RULER = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER;
0154: /**
0155: * Preference key for showing the overview ruler.
0156: */
0157: private final static String OVERVIEW_RULER = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_OVERVIEW_RULER;
0158: /**
0159: * Preference key for highlighting current line.
0160: */
0161: private final static String CURRENT_LINE = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE;
0162: /**
0163: * Preference key for highlight color of current line.
0164: */
0165: private final static String CURRENT_LINE_COLOR = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
0166: /**
0167: * Preference key for showing print margin ruler.
0168: */
0169: private final static String PRINT_MARGIN = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN;
0170: /**
0171: * Preference key for print margin ruler color.
0172: */
0173: private final static String PRINT_MARGIN_COLOR = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
0174: /**
0175: * Preference key for print margin ruler column.
0176: */
0177: private final static String PRINT_MARGIN_COLUMN = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
0178: /**
0179: * Preference key to get whether the overwrite mode is disabled.
0180: * @since 3.1
0181: */
0182: private final static String DISABLE_OVERWRITE_MODE = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE;
0183:
0184: /**
0185: * Adapter class for <code>IGotoMarker</code>.
0186: */
0187: private class GotoMarkerAdapter implements IGotoMarker {
0188: public void gotoMarker(IMarker marker) {
0189: AbstractDecoratedTextEditor.this .gotoMarker(marker);
0190: }
0191: }
0192:
0193: /**
0194: * The annotation preferences.
0195: */
0196: private MarkerAnnotationPreferences fAnnotationPreferences;
0197: /**
0198: * The overview ruler of this editor.
0199: *
0200: * <p>This field should not be referenced by subclasses. It is <code>protected</code> for API
0201: * compatibility reasons and will be made <code>private</code> soon. Use
0202: * {@link #getOverviewRuler()} instead.</p>
0203: */
0204: protected IOverviewRuler fOverviewRuler;
0205: /**
0206: * Helper for accessing annotation from the perspective of this editor.
0207: *
0208: * <p>This field should not be referenced by subclasses. It is <code>protected</code> for API
0209: * compatibility reasons and will be made <code>private</code> soon. Use
0210: * {@link #getAnnotationAccess()} instead.</p>
0211: */
0212: protected IAnnotationAccess fAnnotationAccess;
0213: /**
0214: * Helper for managing the decoration support of this editor's viewer.
0215: *
0216: * <p>This field should not be referenced by subclasses. It is <code>protected</code> for API
0217: * compatibility reasons and will be made <code>private</code> soon. Use
0218: * {@link #getSourceViewerDecorationSupport(ISourceViewer)} instead.</p>
0219: */
0220: protected SourceViewerDecorationSupport fSourceViewerDecorationSupport;
0221: /**
0222: * The line number column.
0223: *
0224: * <p>This field should not be referenced by subclasses. It is <code>protected</code> for API
0225: * compatibility reasons and will be made <code>private</code> soon. Use
0226: * {@link AbstractTextEditor#getVerticalRuler()} to access the vertical bar instead.</p>
0227: */
0228: protected LineNumberRulerColumn fLineNumberRulerColumn;
0229: /**
0230: * The delegating line number ruler contribution.
0231: * @since 3.3
0232: */
0233: private LineNumberColumn fLineColumn;
0234: /**
0235: * The editor's implicit document provider.
0236: */
0237: private IDocumentProvider fImplicitDocumentProvider;
0238: /**
0239: * The editor's goto marker adapter.
0240: */
0241: private Object fGotoMarkerAdapter = new GotoMarkerAdapter();
0242: /**
0243: * Indicates whether this editor is updating views that show markers.
0244: * @see #updateMarkerViews(Annotation)
0245: * @since 3.2
0246: */
0247: protected boolean fIsUpdatingMarkerViews = false;
0248: /**
0249: * Tells whether editing the current derived editor input is allowed.
0250: * @since 3.3
0251: */
0252: private boolean fIsEditingDerivedFileAllowed = true;
0253: /**
0254: * Tells whether the derived state has been validated.
0255: * @since 3.3
0256: */
0257: private boolean fIsDerivedStateValidated = false;
0258:
0259: /*
0260: * Workaround for IllegalAccessError thrown because we are accessing
0261: * a protected method in a different bundle from an inner class.
0262: * @since 3.3
0263: */
0264: private IVerticalRuler internalGetVerticalRuler() {
0265: return getVerticalRuler();
0266: }
0267:
0268: /**
0269: * Creates a new text editor.
0270: */
0271: public AbstractDecoratedTextEditor() {
0272: super ();
0273: fAnnotationPreferences = EditorsPlugin.getDefault()
0274: .getMarkerAnnotationPreferences();
0275: setRangeIndicator(new DefaultRangeIndicator());
0276: initializeKeyBindingScopes();
0277: initializeEditor();
0278: }
0279:
0280: /**
0281: * Initializes this editor. Subclasses may re-implement. If sub-classes do
0282: * not change the contract, this method should not be extended, i.e. do not
0283: * call <code>super.initializeEditor()</code> in order to avoid the
0284: * temporary creation of objects that are immediately overwritten by
0285: * subclasses.
0286: */
0287: protected void initializeEditor() {
0288: setPreferenceStore(EditorsPlugin.getDefault()
0289: .getPreferenceStore());
0290: }
0291:
0292: /**
0293: * Initializes the key binding scopes of this editor.
0294: */
0295: protected void initializeKeyBindingScopes() {
0296: setKeyBindingScopes(new String[] { "org.eclipse.ui.textEditorScope" }); //$NON-NLS-1$
0297: }
0298:
0299: /*
0300: * @see IWorkbenchPart#dispose()
0301: */
0302: public void dispose() {
0303: if (fSourceViewerDecorationSupport != null) {
0304: fSourceViewerDecorationSupport.dispose();
0305: fSourceViewerDecorationSupport = null;
0306: }
0307:
0308: fAnnotationAccess = null;
0309: fAnnotationPreferences = null;
0310:
0311: fLineNumberRulerColumn = null;
0312: fLineColumn = null;
0313:
0314: super .dispose();
0315: }
0316:
0317: /*
0318: * @see org.eclipse.ui.texteditor.AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
0319: */
0320: protected ISourceViewer createSourceViewer(Composite parent,
0321: IVerticalRuler ruler, int styles) {
0322:
0323: fAnnotationAccess = getAnnotationAccess();
0324: fOverviewRuler = createOverviewRuler(getSharedColors());
0325:
0326: ISourceViewer viewer = new SourceViewer(parent, ruler,
0327: getOverviewRuler(), isOverviewRulerVisible(), styles);
0328: // ensure decoration support has been created and configured.
0329: getSourceViewerDecorationSupport(viewer);
0330:
0331: return viewer;
0332: }
0333:
0334: protected ISharedTextColors getSharedColors() {
0335: return EditorsPlugin.getDefault().getSharedTextColors();
0336: }
0337:
0338: protected IOverviewRuler createOverviewRuler(
0339: ISharedTextColors sharedColors) {
0340: IOverviewRuler ruler = new OverviewRuler(getAnnotationAccess(),
0341: VERTICAL_RULER_WIDTH, sharedColors);
0342: Iterator e = fAnnotationPreferences.getAnnotationPreferences()
0343: .iterator();
0344: while (e.hasNext()) {
0345: AnnotationPreference preference = (AnnotationPreference) e
0346: .next();
0347: if (preference.contributesToHeader())
0348: ruler.addHeaderAnnotationType(preference
0349: .getAnnotationType());
0350: }
0351: return ruler;
0352: }
0353:
0354: /**
0355: * Creates the annotation access for this editor.
0356: *
0357: * @return the created annotation access
0358: */
0359: protected IAnnotationAccess createAnnotationAccess() {
0360: return new DefaultMarkerAnnotationAccess();
0361: }
0362:
0363: /**
0364: * Configures the decoration support for this editor's source viewer. Subclasses may override this
0365: * method, but should call their superclass' implementation at some point.
0366: *
0367: * @param support the decoration support to configure
0368: */
0369: protected void configureSourceViewerDecorationSupport(
0370: SourceViewerDecorationSupport support) {
0371:
0372: Iterator e = fAnnotationPreferences.getAnnotationPreferences()
0373: .iterator();
0374: while (e.hasNext())
0375: support.setAnnotationPreference((AnnotationPreference) e
0376: .next());
0377:
0378: support.setCursorLinePainterPreferenceKeys(CURRENT_LINE,
0379: CURRENT_LINE_COLOR);
0380: support.setMarginPainterPreferenceKeys(PRINT_MARGIN,
0381: PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN);
0382: support.setSymbolicFontName(getFontPropertyPreferenceKey());
0383: }
0384:
0385: /*
0386: * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
0387: */
0388: public void createPartControl(Composite parent) {
0389: super .createPartControl(parent);
0390: if (fSourceViewerDecorationSupport != null)
0391: fSourceViewerDecorationSupport
0392: .install(getPreferenceStore());
0393:
0394: IColumnSupport columnSupport = (IColumnSupport) getAdapter(IColumnSupport.class);
0395:
0396: if (isLineNumberRulerVisible()) {
0397: RulerColumnDescriptor lineNumberColumnDescriptor = RulerColumnRegistry
0398: .getDefault().getColumnDescriptor(
0399: LineNumberColumn.ID);
0400: if (lineNumberColumnDescriptor != null)
0401: columnSupport.setColumnVisible(
0402: lineNumberColumnDescriptor, true);
0403: }
0404:
0405: if (isPrefQuickDiffAlwaysOn())
0406: showChangeInformation(true);
0407:
0408: if (!isOverwriteModeEnabled())
0409: enableOverwriteMode(false);
0410:
0411: if (!isRangeIndicatorEnabled()) {
0412: getSourceViewer().removeRangeIndication();
0413: getSourceViewer().setRangeIndicator(null);
0414: }
0415:
0416: // Assign the quick assist assistant to the annotation access.
0417: ISourceViewer viewer = getSourceViewer();
0418: if (fAnnotationAccess instanceof IAnnotationAccessExtension2
0419: && viewer instanceof ISourceViewerExtension3)
0420: ((IAnnotationAccessExtension2) fAnnotationAccess)
0421: .setQuickAssistAssistant(((ISourceViewerExtension3) viewer)
0422: .getQuickAssistAssistant());
0423: }
0424:
0425: /*
0426: * @see org.eclipse.ui.texteditor.StatusTextEditor#createStatusControl(org.eclipse.swt.widgets.Composite, org.eclipse.core.runtime.IStatus)
0427: * @since 3.1
0428: */
0429: protected Control createStatusControl(Composite parent,
0430: final IStatus status) {
0431: Object adapter = getAdapter(IEncodingSupport.class);
0432: DefaultEncodingSupport encodingSupport = null;
0433: if (adapter instanceof DefaultEncodingSupport)
0434: encodingSupport = (DefaultEncodingSupport) adapter;
0435:
0436: if (encodingSupport == null
0437: || !encodingSupport.isEncodingError(status))
0438: return super .createStatusControl(parent, status);
0439:
0440: Shell shell = getSite().getShell();
0441: Display display = shell.getDisplay();
0442: Color bgColor = display
0443: .getSystemColor(SWT.COLOR_LIST_BACKGROUND);
0444: Color fgColor = display
0445: .getSystemColor(SWT.COLOR_LIST_FOREGROUND);
0446:
0447: Composite composite = new Composite(parent, SWT.NONE);
0448: composite.setLayout(new GridLayout());
0449: composite.setBackground(bgColor);
0450: composite.setForeground(fgColor);
0451:
0452: Control control = super .createStatusControl(composite, status);
0453: control.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
0454:
0455: Composite buttonComposite = new Composite(composite, SWT.NONE);
0456: buttonComposite.setLayout(new GridLayout());
0457: buttonComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
0458: buttonComposite.setBackground(bgColor);
0459: buttonComposite.setForeground(fgColor);
0460:
0461: encodingSupport.createStatusEncodingChangeControl(
0462: buttonComposite, status);
0463: //
0464: // Button button= new Button(buttonComposite, SWT.PUSH | SWT.FLAT);
0465: // button.setText(action.getText());
0466: // button.addSelectionListener(new SelectionAdapter() {
0467: // /*
0468: // * @see org.eclipse.swt.events.SelectionAdapter#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
0469: // */
0470: // public void widgetSelected(SelectionEvent e) {
0471: // action.run();
0472: // }
0473: // });
0474: //
0475: // Label filler= new Label(buttonComposite, SWT.NONE);
0476: // filler.setLayoutData(new GridData(GridData.FILL_BOTH));
0477: // filler.setBackground(bgColor);
0478: //
0479: return composite;
0480: }
0481:
0482: /**
0483: * Tells whether the overview ruler is visible.
0484: *
0485: * @return whether the overview ruler is visible
0486: */
0487: protected boolean isOverviewRulerVisible() {
0488: IPreferenceStore store = getPreferenceStore();
0489: return store != null ? store.getBoolean(OVERVIEW_RULER) : false;
0490: }
0491:
0492: /*
0493: * @see org.eclipse.ui.texteditor.ITextEditorExtension3#showChangeInformation(boolean)
0494: */
0495: public void showChangeInformation(boolean show) {
0496: if (show == isChangeInformationShowing())
0497: return;
0498:
0499: IColumnSupport columnSupport = (IColumnSupport) getAdapter(IColumnSupport.class);
0500:
0501: // only handle visibility of the combined column, but not the number/change only state
0502: if (show && fLineColumn == null) {
0503: RulerColumnDescriptor lineNumberColumnDescriptor = RulerColumnRegistry
0504: .getDefault().getColumnDescriptor(
0505: LineNumberColumn.ID);
0506: if (lineNumberColumnDescriptor != null)
0507: columnSupport.setColumnVisible(
0508: lineNumberColumnDescriptor, true);
0509: } else if (!show && fLineColumn != null
0510: && !isLineNumberRulerVisible()) {
0511: columnSupport.setColumnVisible(fLineColumn.getDescriptor(),
0512: false);
0513: fLineColumn = null;
0514: }
0515: }
0516:
0517: /*
0518: * @see org.eclipse.ui.texteditor.ITextEditorExtension3#isChangeInformationShowing()
0519: */
0520: public boolean isChangeInformationShowing() {
0521: return fLineColumn != null
0522: && fLineColumn.isShowingChangeInformation();
0523: }
0524:
0525: /*
0526: * @see org.eclipse.ui.texteditor.ITextEditorExtension4#showRevisionInformation(org.eclipse.jface.text.revisions.RevisionInformation, java.lang.String)
0527: * @since 3.2
0528: */
0529: public void showRevisionInformation(RevisionInformation info,
0530: String quickDiffProviderId) {
0531: if (info.getHoverControlCreator() == null)
0532: info
0533: .setHoverControlCreator(new RevisionHoverInformationControlCreator(
0534: false));
0535:
0536: showChangeInformation(true);
0537: if (fLineColumn != null)
0538: fLineColumn.showRevisionInformation(info,
0539: quickDiffProviderId);
0540: }
0541:
0542: /**
0543: * Returns whether the line number ruler column should be
0544: * visible according to the preference store settings. Subclasses may override this
0545: * method to provide a custom preference setting.
0546: *
0547: * @return <code>true</code> if the line numbers should be visible
0548: */
0549: protected boolean isLineNumberRulerVisible() {
0550: IPreferenceStore store = getPreferenceStore();
0551: return store != null ? store.getBoolean(LINE_NUMBER_RULER)
0552: : false;
0553: }
0554:
0555: /**
0556: * Returns whether the overwrite mode is enabled according to the preference
0557: * store settings. Subclasses may override this method to provide a custom
0558: * preference setting.
0559: *
0560: * @return <code>true</code> if overwrite mode is enabled
0561: * @since 3.1
0562: */
0563: protected boolean isOverwriteModeEnabled() {
0564: IPreferenceStore store = getPreferenceStore();
0565: return store != null ? !store
0566: .getBoolean(DISABLE_OVERWRITE_MODE) : true;
0567: }
0568:
0569: /**
0570: * Returns whether the range indicator is enabled according to the preference
0571: * store settings. Subclasses may override this method to provide a custom
0572: * preference setting.
0573: *
0574: * @return <code>true</code> if overwrite mode is enabled
0575: * @since 3.1
0576: */
0577: private boolean isRangeIndicatorEnabled() {
0578: IPreferenceStore store = getPreferenceStore();
0579: return store != null ? store
0580: .getBoolean(AbstractDecoratedTextEditorPreferenceConstants.SHOW_RANGE_INDICATOR)
0581: : true;
0582: }
0583:
0584: /**
0585: * Returns whether quick diff info should be visible upon opening an editor
0586: * according to the preference store settings.
0587: *
0588: * @return <code>true</code> if the line numbers should be visible
0589: */
0590: protected boolean isPrefQuickDiffAlwaysOn() {
0591: IPreferenceStore store = getPreferenceStore();
0592: boolean setting = store != null ? store
0593: .getBoolean(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON)
0594: : false;
0595: return setting && isEditorInputModifiable();
0596: }
0597:
0598: /**
0599: * Initializes the given line number ruler column from the preference store.
0600: *
0601: * @param rulerColumn the ruler column to be initialized
0602: */
0603: protected void initializeLineNumberRulerColumn(
0604: LineNumberRulerColumn rulerColumn) {
0605: /*
0606: * Left for compatibility. See LineNumberColumn.
0607: */
0608: if (fLineColumn != null)
0609: fLineColumn.initializeLineNumberRulerColumn(rulerColumn);
0610: }
0611:
0612: /**
0613: * Creates a new line number ruler column that is appropriately initialized.
0614: *
0615: * @return the created line number column
0616: */
0617: protected IVerticalRulerColumn createLineNumberRulerColumn() {
0618: /*
0619: * Left for compatibility. See LineNumberColumn.
0620: */
0621: fLineNumberRulerColumn = new LineNumberChangeRulerColumn(
0622: getSharedColors());
0623: ((IChangeRulerColumn) fLineNumberRulerColumn)
0624: .setHover(createChangeHover());
0625: initializeLineNumberRulerColumn(fLineNumberRulerColumn);
0626: return fLineNumberRulerColumn;
0627: }
0628:
0629: /**
0630: * Creates and returns a <code>LineChangeHover</code> to be used on this editor's change
0631: * ruler column. This default implementation returns a plain <code>LineChangeHover</code>.
0632: * Subclasses may override.
0633: *
0634: * @return the change hover to be used by this editors quick diff display
0635: */
0636: protected LineChangeHover createChangeHover() {
0637: return new TextChangeHover();
0638: }
0639:
0640: /**
0641: * Creates a new change ruler column for quick diff display independent of the
0642: * line number ruler column
0643: *
0644: * @return a new change ruler column
0645: * @deprecated as of 3.3. Not called any longer, replaced by {@link #createLineNumberRulerColumn()}
0646: */
0647: protected IChangeRulerColumn createChangeRulerColumn() {
0648: /*
0649: * Left for compatibility. See LineNumberColumn.
0650: */
0651: return new ChangeRulerColumn(getSharedColors());
0652: }
0653:
0654: /**
0655: * Returns {@link #createCompositeRuler()}. Subclasses should not override this method, but
0656: * rather <code>createCompositeRuler</code> if they want to contribute their own vertical ruler
0657: * implementation. If not an instance of {@link CompositeRuler} is returned, the built-in ruler
0658: * columns (line numbers, annotations) will not work.
0659: *
0660: * <p>May become <code>final</code> in the future.</p>
0661: *
0662: * @see AbstractTextEditor#createVerticalRuler()
0663: */
0664: protected IVerticalRuler createVerticalRuler() {
0665: return createCompositeRuler();
0666: }
0667:
0668: /**
0669: * Creates a composite ruler to be used as the vertical ruler by this editor.
0670: * Subclasses may re-implement this method.
0671: *
0672: * @return the vertical ruler
0673: */
0674: protected CompositeRuler createCompositeRuler() {
0675: return new CompositeRuler();
0676: }
0677:
0678: /**
0679: * Creates the annotation ruler column. Subclasses may re-implement or extend.
0680: *
0681: * @param ruler the composite ruler that the column will be added
0682: * @return an annotation ruler column
0683: * @since 3.2
0684: */
0685: protected IVerticalRulerColumn createAnnotationRulerColumn(
0686: CompositeRuler ruler) {
0687: return new AnnotationRulerColumn(VERTICAL_RULER_WIDTH,
0688: getAnnotationAccess());
0689: }
0690:
0691: /*
0692: * @see org.eclipse.ui.texteditor.AbstractTextEditor#createColumnSupport()
0693: * @since 3.3
0694: */
0695: protected final IColumnSupport createColumnSupport() {
0696: return new ColumnSupport(this , RulerColumnRegistry.getDefault()) {
0697: /*
0698: * @see org.eclipse.ui.texteditor.rulers.ColumnSupport#initializeColumn(org.eclipse.ui.texteditor.rulers.AbstractContributedRulerColumn)
0699: */
0700: protected void initializeColumn(
0701: IContributedRulerColumn column) {
0702: super .initializeColumn(column);
0703: RulerColumnDescriptor descriptor = column
0704: .getDescriptor();
0705: IVerticalRuler ruler = internalGetVerticalRuler();
0706: if (ruler instanceof CompositeRuler) {
0707: if (AnnotationColumn.ID.equals(descriptor.getId())) {
0708: ((AnnotationColumn) column)
0709: .setDelegate(createAnnotationRulerColumn((CompositeRuler) ruler));
0710: } else if (LineNumberColumn.ID.equals(descriptor
0711: .getId())) {
0712: fLineColumn = ((LineNumberColumn) column);
0713: fLineColumn
0714: .setForwarder(new LineNumberColumn.ICompatibilityForwarder() {
0715: public IVerticalRulerColumn createLineNumberRulerColumn() {
0716: return AbstractDecoratedTextEditor.this
0717: .createLineNumberRulerColumn();
0718: }
0719:
0720: public boolean isQuickDiffEnabled() {
0721: return AbstractDecoratedTextEditor.this
0722: .isPrefQuickDiffAlwaysOn();
0723: }
0724:
0725: public boolean isLineNumberRulerVisible() {
0726: return AbstractDecoratedTextEditor.this
0727: .isLineNumberRulerVisible();
0728: }
0729: });
0730: }
0731: }
0732: }
0733:
0734: /*
0735: * @see org.eclipse.ui.texteditor.AbstractTextEditor.ColumnSupport#dispose()
0736: */
0737: public void dispose() {
0738: fLineColumn = null;
0739: super .dispose();
0740: }
0741: };
0742: }
0743:
0744: /*
0745: * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
0746: */
0747: protected void handlePreferenceStoreChanged(
0748: PropertyChangeEvent event) {
0749:
0750: try {
0751:
0752: ISourceViewer sourceViewer = getSourceViewer();
0753: if (sourceViewer == null)
0754: return;
0755:
0756: String property = event.getProperty();
0757:
0758: if (fSourceViewerDecorationSupport != null
0759: && fOverviewRuler != null
0760: && OVERVIEW_RULER.equals(property)) {
0761: if (isOverviewRulerVisible())
0762: showOverviewRuler();
0763: else
0764: hideOverviewRuler();
0765: return;
0766: }
0767:
0768: if (DISABLE_OVERWRITE_MODE.equals(property)) {
0769: enableOverwriteMode(isOverwriteModeEnabled());
0770: return;
0771: }
0772:
0773: if (LINE_NUMBER_RULER.equals(property)) {
0774: // only handle visibility of the combined column, but not the number/change only state
0775: IColumnSupport columnSupport = (IColumnSupport) getAdapter(IColumnSupport.class);
0776: if (isLineNumberRulerVisible() && fLineColumn == null) {
0777: RulerColumnDescriptor lineNumberColumnDescriptor = RulerColumnRegistry
0778: .getDefault().getColumnDescriptor(
0779: LineNumberColumn.ID);
0780: if (lineNumberColumnDescriptor != null)
0781: columnSupport.setColumnVisible(
0782: lineNumberColumnDescriptor, true);
0783: } else if (!isLineNumberRulerVisible()
0784: && fLineColumn != null
0785: && !fLineColumn.isShowingChangeInformation()) {
0786: columnSupport.setColumnVisible(fLineColumn
0787: .getDescriptor(), false);
0788: fLineColumn = null;
0789: }
0790: return;
0791: }
0792:
0793: if (AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON
0794: .equals(property)) {
0795: showChangeInformation(isPrefQuickDiffAlwaysOn());
0796: }
0797:
0798: if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH
0799: .equals(property)) {
0800: IPreferenceStore store = getPreferenceStore();
0801: if (store != null)
0802: sourceViewer
0803: .getTextWidget()
0804: .setTabs(
0805: store
0806: .getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH));
0807: if (isTabsToSpacesConversionEnabled()) {
0808: uninstallTabsToSpacesConverter();
0809: installTabsToSpacesConverter();
0810: }
0811: return;
0812: }
0813:
0814: if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS
0815: .equals(property)) {
0816: if (isTabsToSpacesConversionEnabled())
0817: installTabsToSpacesConverter();
0818: else
0819: uninstallTabsToSpacesConverter();
0820: return;
0821: }
0822:
0823: if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_UNDO_HISTORY_SIZE
0824: .equals(property)
0825: && sourceViewer instanceof ITextViewerExtension6) {
0826: IPreferenceStore store = getPreferenceStore();
0827: if (store != null)
0828: ((ITextViewerExtension6) sourceViewer)
0829: .getUndoManager()
0830: .setMaximalUndoLevel(
0831: store
0832: .getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_UNDO_HISTORY_SIZE));
0833: return;
0834: }
0835:
0836: if (AbstractDecoratedTextEditorPreferenceConstants.SHOW_RANGE_INDICATOR
0837: .equals(property)) {
0838: if (isRangeIndicatorEnabled()) {
0839: getSourceViewer().setRangeIndicator(
0840: getRangeIndicator());
0841: } else {
0842: getSourceViewer().removeRangeIndication();
0843: getSourceViewer().setRangeIndicator(null);
0844: }
0845: }
0846:
0847: if (sourceViewer instanceof ITextViewerExtension6) {
0848: HyperlinkDetectorDescriptor[] descriptor = EditorsUI
0849: .getHyperlinkDetectorRegistry()
0850: .getHyperlinkDetectorDescriptors();
0851: for (int i = 0; i < descriptor.length; i++) {
0852: if (descriptor[i].getId().equals(property)
0853: || (descriptor[i].getId() + HyperlinkDetectorDescriptor.STATE_MASK_POSTFIX)
0854: .equals(property)) {
0855: IHyperlinkDetector[] detectors = getSourceViewerConfiguration()
0856: .getHyperlinkDetectors(sourceViewer);
0857: int stateMask = getSourceViewerConfiguration()
0858: .getHyperlinkStateMask(sourceViewer);
0859: ITextViewerExtension6 textViewer6 = (ITextViewerExtension6) sourceViewer;
0860: textViewer6.setHyperlinkDetectors(detectors,
0861: stateMask);
0862: return;
0863: }
0864: }
0865: }
0866:
0867: } finally {
0868: super .handlePreferenceStoreChanged(event);
0869: }
0870: }
0871:
0872: /**
0873: * Shows the overview ruler.
0874: */
0875: protected void showOverviewRuler() {
0876: if (fOverviewRuler != null) {
0877: if (getSourceViewer() instanceof ISourceViewerExtension) {
0878: ((ISourceViewerExtension) getSourceViewer())
0879: .showAnnotationsOverview(true);
0880: fSourceViewerDecorationSupport
0881: .updateOverviewDecorations();
0882: }
0883: }
0884: }
0885:
0886: /**
0887: * Hides the overview ruler.
0888: */
0889: protected void hideOverviewRuler() {
0890: if (getSourceViewer() instanceof ISourceViewerExtension) {
0891: fSourceViewerDecorationSupport.hideAnnotationOverview();
0892: ((ISourceViewerExtension) getSourceViewer())
0893: .showAnnotationsOverview(false);
0894: }
0895: }
0896:
0897: /**
0898: * Returns the annotation access.
0899: *
0900: * @return the annotation access
0901: */
0902: protected IAnnotationAccess getAnnotationAccess() {
0903: if (fAnnotationAccess == null)
0904: fAnnotationAccess = createAnnotationAccess();
0905: return fAnnotationAccess;
0906: }
0907:
0908: /**
0909: * Returns the annotation preference lookup.
0910: *
0911: * @return the annotation preference lookup
0912: */
0913: protected AnnotationPreferenceLookup getAnnotationPreferenceLookup() {
0914: return EditorsPlugin.getDefault()
0915: .getAnnotationPreferenceLookup();
0916: }
0917:
0918: /**
0919: * Returns the overview ruler.
0920: *
0921: * @return the overview ruler
0922: */
0923: protected IOverviewRuler getOverviewRuler() {
0924: if (fOverviewRuler == null)
0925: fOverviewRuler = createOverviewRuler(getSharedColors());
0926: return fOverviewRuler;
0927: }
0928:
0929: /**
0930: * Returns the source viewer decoration support.
0931: *
0932: * @param viewer the viewer for which to return a decoration support
0933: * @return the source viewer decoration support
0934: */
0935: protected SourceViewerDecorationSupport getSourceViewerDecorationSupport(
0936: ISourceViewer viewer) {
0937: if (fSourceViewerDecorationSupport == null) {
0938: fSourceViewerDecorationSupport = new SourceViewerDecorationSupport(
0939: viewer, getOverviewRuler(), getAnnotationAccess(),
0940: getSharedColors());
0941: configureSourceViewerDecorationSupport(fSourceViewerDecorationSupport);
0942: }
0943: return fSourceViewerDecorationSupport;
0944: }
0945:
0946: /**
0947: * Returns the annotation preferences.
0948: *
0949: * @return the annotation preferences
0950: */
0951: protected MarkerAnnotationPreferences getAnnotationPreferences() {
0952: return fAnnotationPreferences;
0953: }
0954:
0955: /**
0956: * If the editor can be saved all marker ranges have been changed according to
0957: * the text manipulations. However, those changes are not yet propagated to the
0958: * marker manager. Thus, when opening a marker, the marker's position in the editor
0959: * must be determined as it might differ from the position stated in the marker.
0960: *
0961: * @param marker the marker to go to
0962: * @deprecated visibility will be reduced, use <code>getAdapter(IGotoMarker.class) for accessing this method</code>
0963: */
0964: public void gotoMarker(IMarker marker) {
0965: if (fIsUpdatingMarkerViews)
0966: return;
0967:
0968: if (getSourceViewer() == null)
0969: return;
0970:
0971: int start = MarkerUtilities.getCharStart(marker);
0972: int end = MarkerUtilities.getCharEnd(marker);
0973:
0974: boolean selectLine = start < 0 || end < 0;
0975:
0976: // look up the current range of the marker when the document has been edited
0977: IAnnotationModel model = getDocumentProvider()
0978: .getAnnotationModel(getEditorInput());
0979: if (model instanceof AbstractMarkerAnnotationModel) {
0980:
0981: AbstractMarkerAnnotationModel markerModel = (AbstractMarkerAnnotationModel) model;
0982: Position pos = markerModel.getMarkerPosition(marker);
0983: if (pos != null && !pos.isDeleted()) {
0984: // use position instead of marker values
0985: start = pos.getOffset();
0986: end = pos.getOffset() + pos.getLength();
0987: }
0988:
0989: if (pos != null && pos.isDeleted()) {
0990: // do nothing if position has been deleted
0991: return;
0992: }
0993: }
0994:
0995: IDocument document = getDocumentProvider().getDocument(
0996: getEditorInput());
0997:
0998: if (selectLine) {
0999: int line;
1000: try {
1001: if (start >= 0)
1002: line = document.getLineOfOffset(start);
1003: else {
1004: line = MarkerUtilities.getLineNumber(marker);
1005: // Marker line numbers are 1-based
1006: --line;
1007: start = document.getLineOffset(line);
1008: }
1009: end = start + document.getLineLength(line) - 1;
1010: } catch (BadLocationException e) {
1011: return;
1012: }
1013: }
1014:
1015: int length = document.getLength();
1016: if (end - 1 < length && start < length)
1017: selectAndReveal(start, end - start);
1018: }
1019:
1020: /*
1021: * @see org.eclipse.ui.texteditor.AbstractTextEditor#isEditable()
1022: * @since 3.3
1023: */
1024: public boolean isEditable() {
1025: if (!super .isEditable())
1026: return false;
1027: return fIsEditingDerivedFileAllowed;
1028: }
1029:
1030: /*
1031: * @see org.eclipse.ui.texteditor.StatusTextEditor#validateEditorInputState()
1032: * @since 3.3
1033: */
1034: public boolean validateEditorInputState() {
1035: if (!super .validateEditorInputState())
1036: return false;
1037:
1038: return validateEditorInputDerived();
1039: }
1040:
1041: /**
1042: * Validates the editor input for derived state.
1043: * If the given input is derived then this method
1044: * can show a dialog asking whether to edit the
1045: * derived file.
1046: *
1047: * @return <code>true</code> if the input is OK for editing, <code>false</code> otherwise
1048: * @since 3.3
1049: */
1050: private boolean validateEditorInputDerived() {
1051: if (fIsDerivedStateValidated)
1052: return fIsEditingDerivedFileAllowed;
1053:
1054: if (getDocumentProvider() instanceof IDocumentProviderExtension) {
1055: IDocumentProviderExtension extension = (IDocumentProviderExtension) getDocumentProvider();
1056: IStatus status = extension.getStatus(getEditorInput());
1057: String pluginId = status.getPlugin();
1058: boolean isDerivedStatus = status.getCode() == IFileBufferStatusCodes.DERIVED_FILE
1059: && (FileBuffers.PLUGIN_ID.equals(pluginId) || EditorsUI.PLUGIN_ID
1060: .equals(pluginId));
1061: if (!isDerivedStatus)
1062: return true;
1063: }
1064:
1065: final String warnKey = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_WARN_IF_INPUT_DERIVED;
1066: IPreferenceStore store = getPreferenceStore();
1067: if (!store.getBoolean(warnKey))
1068: return true;
1069:
1070: MessageDialogWithToggle toggleDialog = MessageDialogWithToggle
1071: .openYesNoQuestion(
1072: getSite().getShell(),
1073: TextEditorMessages.AbstractDecoratedTextEditor_warning_derived_title,
1074: TextEditorMessages.AbstractDecoratedTextEditor_warning_derived_message,
1075: TextEditorMessages.AbstractDecoratedTextEditor_warning_derived_dontShowAgain,
1076: false, null, null);
1077:
1078: EditorsUI.getPreferenceStore().setValue(warnKey,
1079: !toggleDialog.getToggleState());
1080: fIsDerivedStateValidated = true;
1081: return fIsEditingDerivedFileAllowed = toggleDialog
1082: .getReturnCode() == IDialogConstants.YES_ID;
1083: }
1084:
1085: /*
1086: * For an explanation why we override this method see:
1087: * bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=42230
1088: *
1089: * @see org.eclipse.ui.texteditor.StatusTextEditor#isErrorStatus(org.eclipse.core.runtime.IStatus)
1090: */
1091: protected boolean isErrorStatus(IStatus status) {
1092: if (!super .isErrorStatus(status))
1093: return false;
1094:
1095: if (!status.isMultiStatus())
1096: return !isReadOnlyLocalStatus(status);
1097:
1098: IStatus[] childrenStatus = status.getChildren();
1099: for (int i = 0; i < childrenStatus.length; i++) {
1100: if (childrenStatus[i].getSeverity() == IStatus.ERROR
1101: && !isReadOnlyLocalStatus(childrenStatus[i]))
1102: return true;
1103: }
1104:
1105: return false;
1106: }
1107:
1108: /**
1109: * Check whether the given status is a <code>IResourceStatus.READ_ONLY_LOCAL</code>
1110: * error.
1111: *
1112: * @param status the status to be checked
1113: * @return <code>true</code> if the given status is a <code>IResourceStatus.READ_ONLY_LOCAL</code> error
1114: * @since 3.3
1115: */
1116: private boolean isReadOnlyLocalStatus(IStatus status) {
1117: return status.getCode() == IResourceStatus.READ_ONLY_LOCAL;
1118: }
1119:
1120: /*
1121: * @see org.eclipse.ui.texteditor.AbstractTextEditor#createActions()
1122: */
1123: protected void createActions() {
1124: super .createActions();
1125:
1126: ResourceAction action = new AddMarkerAction(TextEditorMessages
1127: .getBundleForConstructedKeys(),
1128: "Editor.AddBookmark.", this , IMarker.BOOKMARK, true); //$NON-NLS-1$
1129: action
1130: .setHelpContextId(ITextEditorHelpContextIds.BOOKMARK_ACTION);
1131: action
1132: .setActionDefinitionId(IWorkbenchActionDefinitionIds.ADD_BOOKMARK);
1133: setAction(IDEActionFactory.BOOKMARK.getId(), action);
1134:
1135: action = new AddTaskAction(TextEditorMessages
1136: .getBundleForConstructedKeys(), "Editor.AddTask.", this ); //$NON-NLS-1$
1137: action
1138: .setHelpContextId(ITextEditorHelpContextIds.ADD_TASK_ACTION);
1139: action
1140: .setActionDefinitionId(IWorkbenchActionDefinitionIds.ADD_TASK);
1141: setAction(IDEActionFactory.ADD_TASK.getId(), action);
1142:
1143: action = new ChangeEncodingAction(TextEditorMessages
1144: .getBundleForConstructedKeys(),
1145: "Editor.ChangeEncodingAction.", this ); //$NON-NLS-1$
1146: action
1147: .setHelpContextId(ITextEditorHelpContextIds.CHANGE_ENCODING);
1148: action
1149: .setActionDefinitionId(ITextEditorActionDefinitionIds.CHANGE_ENCODING);
1150: setAction(ITextEditorActionConstants.CHANGE_ENCODING, action);
1151: markAsPropertyDependentAction(
1152: ITextEditorActionConstants.CHANGE_ENCODING, true);
1153:
1154: action = new ResourceAction(TextEditorMessages
1155: .getBundleForConstructedKeys(),
1156: "Editor.ToggleLineNumbersAction.", IAction.AS_CHECK_BOX) { //$NON-NLS-1$
1157: public void run() {
1158: toggleLineNumberRuler();
1159: }
1160: };
1161: action
1162: .setActionDefinitionId(ITextEditorActionDefinitionIds.LINENUMBER_TOGGLE);
1163: setAction(ITextEditorActionConstants.LINENUMBERS_TOGGLE, action);
1164:
1165: action = new ResourceAction(TextEditorMessages
1166: .getBundleForConstructedKeys(),
1167: "Editor.ToggleQuickDiffAction.", IAction.AS_CHECK_BOX) { //$NON-NLS-1$
1168: public void run() {
1169: toggleQuickDiffRuler();
1170: }
1171: };
1172: action
1173: .setActionDefinitionId(ITextEditorActionDefinitionIds.QUICKDIFF_TOGGLE);
1174: setAction(ITextEditorActionConstants.QUICKDIFF_TOGGLE, action);
1175:
1176: action = new RevertLineAction(this , false);
1177: action
1178: .setActionDefinitionId(ITextEditorActionDefinitionIds.QUICKDIFF_REVERTLINE);
1179: setAction(ITextEditorActionConstants.QUICKDIFF_REVERTLINE,
1180: action);
1181:
1182: action = new RevertSelectionAction(this , false);
1183: setAction(ITextEditorActionConstants.QUICKDIFF_REVERTSELECTION,
1184: action);
1185:
1186: action = new RevertBlockAction(this , false);
1187: setAction(ITextEditorActionConstants.QUICKDIFF_REVERTBLOCK,
1188: action);
1189:
1190: action = new RestoreAction(this , false);
1191: setAction(ITextEditorActionConstants.QUICKDIFF_REVERTDELETION,
1192: action);
1193:
1194: IAction action2 = new CompositeRevertAction(
1195: this ,
1196: new IAction[] {
1197: getAction(ITextEditorActionConstants.QUICKDIFF_REVERTSELECTION),
1198: getAction(ITextEditorActionConstants.QUICKDIFF_REVERTBLOCK),
1199: getAction(ITextEditorActionConstants.QUICKDIFF_REVERTDELETION),
1200: getAction(ITextEditorActionConstants.QUICKDIFF_REVERTLINE) });
1201: action2
1202: .setActionDefinitionId(ITextEditorActionDefinitionIds.QUICKDIFF_REVERT);
1203: setAction(ITextEditorActionConstants.QUICKDIFF_REVERT, action2);
1204:
1205: action = new ResourceAction(TextEditorMessages
1206: .getBundleForConstructedKeys(),
1207: "Editor.HideRevisionInformationAction.") { //$NON-NLS-1$
1208: public void run() {
1209: if (fLineColumn != null)
1210: fLineColumn.hideRevisionInformation();
1211: }
1212: };
1213: setAction(ITextEditorActionConstants.REVISION_HIDE_INFO, action);
1214:
1215: action = new ResourceAction(TextEditorMessages
1216: .getBundleForConstructedKeys(),
1217: "Editor.CycleRevisionRenderingAction.") { //$NON-NLS-1$
1218: public void run() {
1219: final RenderingMode[] modes = {
1220: IRevisionRulerColumnExtension.AGE,
1221: IRevisionRulerColumnExtension.AUTHOR,
1222: IRevisionRulerColumnExtension.AUTHOR_SHADED_BY_AGE };
1223: IPreferenceStore store = EditorsUI.getPreferenceStore();
1224: String current = store
1225: .getString(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE);
1226: for (int i = 0; i < modes.length; i++) {
1227: String mode = modes[i].name();
1228: if (mode.equals(current)) {
1229: int nextIndex = (i + 1) % modes.length;
1230: RenderingMode nextMode = modes[nextIndex];
1231: store
1232: .setValue(
1233: AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE,
1234: nextMode.name());
1235: }
1236: }
1237: }
1238: };
1239: action
1240: .setActionDefinitionId(ITextEditorActionDefinitionIds.REVISION_RENDERING_CYCLE);
1241: setAction(ITextEditorActionConstants.REVISION_RENDERING_CYCLE,
1242: action);
1243:
1244: action = new BooleanPreferenceToggleAction(
1245: TextEditorMessages.getBundleForConstructedKeys(),
1246: "Editor.ToggleRevisionAuthorAction.", IAction.AS_CHECK_BOX, EditorsUI.getPreferenceStore(), AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_AUTHOR); //$NON-NLS-1$
1247: action
1248: .setActionDefinitionId(ITextEditorActionDefinitionIds.REVISION_AUTHOR_TOGGLE);
1249: setAction(
1250: ITextEditorActionConstants.REVISION_SHOW_AUTHOR_TOGGLE,
1251: action);
1252:
1253: action = new BooleanPreferenceToggleAction(
1254: TextEditorMessages.getBundleForConstructedKeys(),
1255: "Editor.ToggleRevisionIdAction.", IAction.AS_CHECK_BOX, EditorsUI.getPreferenceStore(), AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_REVISION); //$NON-NLS-1$
1256: action
1257: .setActionDefinitionId(ITextEditorActionDefinitionIds.REVISION_ID_TOGGLE);
1258: setAction(ITextEditorActionConstants.REVISION_SHOW_ID_TOGGLE,
1259: action);
1260:
1261: final Shell shell;
1262: if (getSourceViewer() != null)
1263: shell = getSourceViewer().getTextWidget().getShell();
1264: else
1265: shell = null;
1266: action = new ResourceAction(TextEditorMessages
1267: .getBundleForConstructedKeys(),
1268: "Editor.RulerPreferencesAction.") { //$NON-NLS-1$
1269: public void run() {
1270: String[] preferencePages = collectRulerMenuPreferencePages();
1271: if (preferencePages.length > 0
1272: && (shell == null || !shell.isDisposed()))
1273: PreferencesUtil.createPreferenceDialogOn(shell,
1274: preferencePages[0], preferencePages, null)
1275: .open();
1276: }
1277:
1278: };
1279: setAction(ITextEditorActionConstants.RULER_PREFERENCES, action);
1280:
1281: action = new ResourceAction(TextEditorMessages
1282: .getBundleForConstructedKeys(),
1283: "Editor.ContextPreferencesAction.") { //$NON-NLS-1$
1284: public void run() {
1285: String[] preferencePages = collectContextMenuPreferencePages();
1286: if (preferencePages.length > 0
1287: && (shell == null || !shell.isDisposed()))
1288: PreferencesUtil.createPreferenceDialogOn(shell,
1289: preferencePages[0], preferencePages, null)
1290: .open();
1291: }
1292: };
1293: action.setId(ITextEditorActionConstants.CONTEXT_PREFERENCES);
1294: setAction(ITextEditorActionConstants.CONTEXT_PREFERENCES,
1295: action);
1296:
1297: IAction showWhitespaceCharactersAction = getAction(ITextEditorActionConstants.SHOW_WHITESPACE_CHARACTERS);
1298: if (showWhitespaceCharactersAction instanceof ShowWhitespaceCharactersAction)
1299: ((ShowWhitespaceCharactersAction) showWhitespaceCharactersAction)
1300: .setPreferenceStore(EditorsUI.getPreferenceStore());
1301:
1302: setAction(ITextEditorActionConstants.REFRESH,
1303: new RefreshEditorAction(this ));
1304: markAsPropertyDependentAction(
1305: ITextEditorActionConstants.REFRESH, true);
1306: }
1307:
1308: public Object getAdapter(Class adapter) {
1309: if (IGotoMarker.class.equals(adapter))
1310: return fGotoMarkerAdapter;
1311:
1312: if (IAnnotationAccess.class.equals(adapter))
1313: return getAnnotationAccess();
1314:
1315: if (adapter == IShowInSource.class) {
1316: return new IShowInSource() {
1317: public ShowInContext getShowInContext() {
1318: ISelection selection = null;
1319: ISelectionProvider selectionProvider = getSelectionProvider();
1320: if (selectionProvider != null)
1321: selection = selectionProvider.getSelection();
1322: return new ShowInContext(getEditorInput(),
1323: selection);
1324: }
1325: };
1326: }
1327:
1328: if (IRevisionRulerColumn.class.equals(adapter)) {
1329: if (fLineNumberRulerColumn instanceof IRevisionRulerColumn)
1330: return fLineNumberRulerColumn;
1331: }
1332:
1333: return super .getAdapter(adapter);
1334:
1335: }
1336:
1337: /*
1338: * If there is no explicit document provider set, the implicit one is
1339: * re-initialized based on the given editor input.
1340: *
1341: * @see org.eclipse.ui.texteditor.AbstractTextEditor#setDocumentProvider(org.eclipse.ui.IEditorInput)
1342: */
1343: protected void setDocumentProvider(IEditorInput input) {
1344: fImplicitDocumentProvider = DocumentProviderRegistry
1345: .getDefault().getDocumentProvider(input);
1346: IDocumentProvider provider = super .getDocumentProvider();
1347: if (provider instanceof ForwardingDocumentProvider) {
1348: ForwardingDocumentProvider forwarder = (ForwardingDocumentProvider) provider;
1349: forwarder.setParentProvider(fImplicitDocumentProvider);
1350: }
1351: }
1352:
1353: /*
1354: * @see org.eclipse.ui.texteditor.ITextEditor#getDocumentProvider()
1355: */
1356: public IDocumentProvider getDocumentProvider() {
1357: IDocumentProvider provider = super .getDocumentProvider();
1358: if (provider == null)
1359: return fImplicitDocumentProvider;
1360: return provider;
1361: }
1362:
1363: /*
1364: * @see org.eclipse.ui.texteditor.AbstractTextEditor#disposeDocumentProvider()
1365: */
1366: protected void disposeDocumentProvider() {
1367: super .disposeDocumentProvider();
1368: fImplicitDocumentProvider = null;
1369: }
1370:
1371: /*
1372: * @see AbstractTextEditor#doSetInput(IEditorInput)
1373: *
1374: * This implementation also updates change information in the quick diff
1375: * ruler.
1376: */
1377: protected void doSetInput(IEditorInput input) throws CoreException {
1378: fIsDerivedStateValidated = false;
1379: fIsEditingDerivedFileAllowed = true;
1380:
1381: if (fLineColumn != null)
1382: fLineColumn.hideRevisionInformation();
1383:
1384: super .doSetInput(input);
1385:
1386: RulerColumnDescriptor lineNumberColumnDescriptor = RulerColumnRegistry
1387: .getDefault().getColumnDescriptor(LineNumberColumn.ID);
1388: if (lineNumberColumnDescriptor != null) {
1389: IColumnSupport columnSupport = (IColumnSupport) getAdapter(IColumnSupport.class);
1390: columnSupport.setColumnVisible(lineNumberColumnDescriptor,
1391: isLineNumberRulerVisible()
1392: || isPrefQuickDiffAlwaysOn());
1393: }
1394: }
1395:
1396: /**
1397: * This implementation asks the user for the workspace path of a file resource and saves the document there.
1398: *
1399: * @param progressMonitor the progress monitor to be used
1400: * @since 3.2
1401: */
1402: protected void performSaveAs(IProgressMonitor progressMonitor) {
1403: Shell shell = getSite().getShell();
1404: final IEditorInput input = getEditorInput();
1405:
1406: IDocumentProvider provider = getDocumentProvider();
1407: final IEditorInput newInput;
1408:
1409: if (input instanceof IURIEditorInput
1410: && !(input instanceof IFileEditorInput)) {
1411: FileDialog dialog = new FileDialog(shell, SWT.SAVE);
1412: IPath oldPath = URIUtil.toPath(((IURIEditorInput) input)
1413: .getURI());
1414: if (oldPath != null) {
1415: dialog.setFileName(oldPath.lastSegment());
1416: dialog.setFilterPath(oldPath.toOSString());
1417: }
1418:
1419: String path = dialog.open();
1420: if (path == null) {
1421: if (progressMonitor != null)
1422: progressMonitor.setCanceled(true);
1423: return;
1424: }
1425:
1426: // Check whether file exists and if so, confirm overwrite
1427: final File localFile = new File(path);
1428: if (localFile.exists()) {
1429: MessageDialog overwriteDialog = new MessageDialog(
1430: shell,
1431: TextEditorMessages.AbstractDecoratedTextEditor_saveAs_overwrite_title,
1432: null,
1433: NLSUtility
1434: .format(
1435: TextEditorMessages.AbstractDecoratedTextEditor_saveAs_overwrite_message,
1436: path), MessageDialog.WARNING,
1437: new String[] { IDialogConstants.YES_LABEL,
1438: IDialogConstants.NO_LABEL }, 1); // 'No' is the default
1439: if (overwriteDialog.open() != Window.OK) {
1440: if (progressMonitor != null) {
1441: progressMonitor.setCanceled(true);
1442: return;
1443: }
1444: }
1445: }
1446:
1447: IFileStore fileStore;
1448: try {
1449: fileStore = EFS.getStore(localFile.toURI());
1450: } catch (CoreException ex) {
1451: EditorsPlugin.log(ex.getStatus());
1452: String title = TextEditorMessages.AbstractDecoratedTextEditor_error_saveAs_title;
1453: String msg = NLSUtility
1454: .format(
1455: TextEditorMessages.AbstractDecoratedTextEditor_error_saveAs_message,
1456: ex.getMessage());
1457: MessageDialog.openError(shell, title, msg);
1458: return;
1459: }
1460:
1461: IFile file = getWorkspaceFile(fileStore);
1462: if (file != null)
1463: newInput = new FileEditorInput(file);
1464: else
1465: newInput = new FileStoreEditorInput(fileStore);
1466:
1467: } else {
1468: SaveAsDialog dialog = new SaveAsDialog(shell);
1469:
1470: IFile original = (input instanceof IFileEditorInput) ? ((IFileEditorInput) input)
1471: .getFile()
1472: : null;
1473: if (original != null)
1474: dialog.setOriginalFile(original);
1475:
1476: dialog.create();
1477:
1478: if (provider.isDeleted(input) && original != null) {
1479: String message = NLSUtility
1480: .format(
1481: TextEditorMessages.AbstractDecoratedTextEditor_warning_saveAs_deleted,
1482: original.getName());
1483: dialog.setErrorMessage(null);
1484: dialog.setMessage(message, IMessageProvider.WARNING);
1485: }
1486:
1487: if (dialog.open() == Window.CANCEL) {
1488: if (progressMonitor != null)
1489: progressMonitor.setCanceled(true);
1490: return;
1491: }
1492:
1493: IPath filePath = dialog.getResult();
1494: if (filePath == null) {
1495: if (progressMonitor != null)
1496: progressMonitor.setCanceled(true);
1497: return;
1498: }
1499:
1500: IWorkspace workspace = ResourcesPlugin.getWorkspace();
1501: IFile file = workspace.getRoot().getFile(filePath);
1502: newInput = new FileEditorInput(file);
1503:
1504: }
1505:
1506: if (provider == null) {
1507: // editor has programmatically been closed while the dialog was open
1508: return;
1509: }
1510:
1511: boolean success = false;
1512: try {
1513:
1514: provider.aboutToChange(newInput);
1515: provider.saveDocument(progressMonitor, newInput, provider
1516: .getDocument(input), true);
1517: success = true;
1518:
1519: } catch (CoreException x) {
1520: final IStatus status = x.getStatus();
1521: if (status == null
1522: || status.getSeverity() != IStatus.CANCEL) {
1523: String title = TextEditorMessages.AbstractDecoratedTextEditor_error_saveAs_title;
1524: String msg = NLSUtility
1525: .format(
1526: TextEditorMessages.AbstractDecoratedTextEditor_error_saveAs_message,
1527: x.getMessage());
1528: MessageDialog.openError(shell, title, msg);
1529: }
1530: } finally {
1531: provider.changed(newInput);
1532: if (success)
1533: setInput(newInput);
1534: }
1535:
1536: if (progressMonitor != null)
1537: progressMonitor.setCanceled(!success);
1538: }
1539:
1540: /**
1541: * Checks whether there given file store points
1542: * to a file in the workspace. Only returns a
1543: * workspace file if there's a single match.
1544: *
1545: * @param fileStore the file store
1546: * @return the <code>IFile</code> that matches the given file store
1547: * @since 3.2
1548: */
1549: private IFile getWorkspaceFile(IFileStore fileStore) {
1550: IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace()
1551: .getRoot();
1552: IFile[] files = workspaceRoot.findFilesForLocation(URIUtil
1553: .toPath(fileStore.toURI()));
1554: if (files != null && files.length == 1)
1555: return files[0];
1556: return null;
1557: }
1558:
1559: /*
1560: * @see org.eclipse.ui.texteditor.AbstractTextEditor#rulerContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager)
1561: * @since 3.1
1562: */
1563: protected void rulerContextMenuAboutToShow(IMenuManager menu) {
1564: /*
1565: * XXX: workaround for reliable menu item ordering.
1566: * This can be changed once the action contribution story converges,
1567: * see http://dev.eclipse.org/viewcvs/index.cgi/~checkout~/platform-ui-home/R3_1/dynamic_teams/dynamic_teams.html#actionContributions
1568: */
1569: // pre-install menus for contributions and call super
1570: menu.add(new Separator("debug")); //$NON-NLS-1$
1571: menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
1572: menu.add(new GroupMarker(
1573: ITextEditorActionConstants.GROUP_RESTORE));
1574: menu.add(new Separator("add")); //$NON-NLS-1$
1575: menu
1576: .add(new Separator(
1577: ITextEditorActionConstants.GROUP_RULERS));
1578: menu.add(new Separator(ITextEditorActionConstants.GROUP_REST));
1579:
1580: super .rulerContextMenuAboutToShow(menu);
1581:
1582: addRulerContributionActions(menu);
1583:
1584: /* quick diff */
1585: if (isEditorInputModifiable()) {
1586: IAction quickdiffAction = getAction(ITextEditorActionConstants.QUICKDIFF_TOGGLE);
1587: quickdiffAction.setChecked(isChangeInformationShowing());
1588: menu.appendToGroup(ITextEditorActionConstants.GROUP_RULERS,
1589: quickdiffAction);
1590:
1591: if (isChangeInformationShowing()) {
1592: TextEditorAction revertLine = new RevertLineAction(
1593: this , true);
1594: TextEditorAction revertSelection = new RevertSelectionAction(
1595: this , true);
1596: TextEditorAction revertBlock = new RevertBlockAction(
1597: this , true);
1598: TextEditorAction revertDeletion = new RestoreAction(
1599: this , true);
1600:
1601: revertSelection.update();
1602: revertBlock.update();
1603: revertLine.update();
1604: revertDeletion.update();
1605:
1606: // only add block action if selection action is not enabled
1607: if (revertSelection.isEnabled())
1608: menu.appendToGroup(
1609: ITextEditorActionConstants.GROUP_RESTORE,
1610: revertSelection);
1611: else if (revertBlock.isEnabled())
1612: menu.appendToGroup(
1613: ITextEditorActionConstants.GROUP_RESTORE,
1614: revertBlock);
1615: if (revertLine.isEnabled())
1616: menu.appendToGroup(
1617: ITextEditorActionConstants.GROUP_RESTORE,
1618: revertLine);
1619: if (revertDeletion.isEnabled())
1620: menu.appendToGroup(
1621: ITextEditorActionConstants.GROUP_RESTORE,
1622: revertDeletion);
1623: }
1624: }
1625:
1626: // revision info
1627: if (fLineColumn != null
1628: && fLineColumn.isShowingRevisionInformation()) {
1629: IMenuManager revisionMenu = new MenuManager(
1630: TextEditorMessages.AbstractDecoratedTextEditor_revisions_menu);
1631: menu.appendToGroup(ITextEditorActionConstants.GROUP_RULERS,
1632: revisionMenu);
1633:
1634: IAction hideRevisionInfoAction = getAction(ITextEditorActionConstants.REVISION_HIDE_INFO);
1635: revisionMenu.add(hideRevisionInfoAction);
1636: revisionMenu.add(new Separator());
1637:
1638: String[] labels = {
1639: TextEditorMessages.AbstractDecoratedTextEditor_revision_colors_option_by_date,
1640: TextEditorMessages.AbstractDecoratedTextEditor_revision_colors_option_by_author,
1641: TextEditorMessages.AbstractDecoratedTextEditor_revision_colors_option_by_author_and_date };
1642: final RenderingMode[] modes = {
1643: IRevisionRulerColumnExtension.AGE,
1644: IRevisionRulerColumnExtension.AUTHOR,
1645: IRevisionRulerColumnExtension.AUTHOR_SHADED_BY_AGE };
1646: final IPreferenceStore uiStore = EditorsUI
1647: .getPreferenceStore();
1648: String current = uiStore
1649: .getString(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE);
1650: for (int i = 0; i < modes.length; i++) {
1651: final String mode = modes[i].name();
1652: IAction action = new Action(labels[i],
1653: IAction.AS_RADIO_BUTTON) {
1654: public void run() {
1655: // set preference globally, LineNumberColumn reacts on preference change
1656: uiStore
1657: .setValue(
1658: AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE,
1659: mode);
1660: }
1661: };
1662: action.setChecked(mode.equals(current));
1663: revisionMenu.add(action);
1664: }
1665:
1666: revisionMenu.add(new Separator());
1667:
1668: revisionMenu
1669: .add(getAction(ITextEditorActionConstants.REVISION_SHOW_AUTHOR_TOGGLE));
1670: revisionMenu
1671: .add(getAction(ITextEditorActionConstants.REVISION_SHOW_ID_TOGGLE));
1672: }
1673:
1674: IAction lineNumberAction = getAction(ITextEditorActionConstants.LINENUMBERS_TOGGLE);
1675: lineNumberAction.setChecked(fLineColumn != null
1676: && fLineColumn.isShowingLineNumbers());
1677: menu.appendToGroup(ITextEditorActionConstants.GROUP_RULERS,
1678: lineNumberAction);
1679:
1680: IAction preferencesAction = getAction(ITextEditorActionConstants.RULER_PREFERENCES);
1681: menu
1682: .appendToGroup(
1683: ITextEditorActionConstants.GROUP_RULERS,
1684: new Separator(
1685: ITextEditorActionConstants.GROUP_SETTINGS));
1686: menu.appendToGroup(ITextEditorActionConstants.GROUP_SETTINGS,
1687: preferencesAction);
1688: }
1689:
1690: /**
1691: * Adds "show" actions for all contributed rulers that support it.
1692: *
1693: * @param menu the ruler context menu
1694: * @since 3.3
1695: */
1696: private void addRulerContributionActions(IMenuManager menu) {
1697: // store directly in generic editor preferences
1698: final IColumnSupport support = (IColumnSupport) getAdapter(IColumnSupport.class);
1699: IPreferenceStore store = EditorsUI.getPreferenceStore();
1700: final RulerColumnPreferenceAdapter adapter = new RulerColumnPreferenceAdapter(
1701: store,
1702: AbstractTextEditor.PREFERENCE_RULER_CONTRIBUTIONS);
1703: List descriptors = RulerColumnRegistry.getDefault()
1704: .getColumnDescriptors();
1705: for (Iterator t = descriptors.iterator(); t.hasNext();) {
1706: final RulerColumnDescriptor descriptor = (RulerColumnDescriptor) t
1707: .next();
1708: if (!descriptor.isIncludedInMenu()
1709: || !support.isColumnSupported(descriptor))
1710: continue;
1711: final boolean isVisible = support
1712: .isColumnVisible(descriptor);
1713: IAction action = new Action(
1714: MessageFormat
1715: .format(
1716: TextEditorMessages.AbstractDecoratedTextEditor_show_ruler_label,
1717: new Object[] { descriptor.getName() }),
1718: IAction.AS_CHECK_BOX) {
1719: public void run() {
1720: if (descriptor.isGlobal())
1721: // column state is modified via preference listener of AbstractTextEditor
1722: adapter.setEnabled(descriptor, !isVisible);
1723: else
1724: // directly modify column for this editor instance
1725: support
1726: .setColumnVisible(descriptor,
1727: !isVisible);
1728: }
1729: };
1730: action.setChecked(isVisible);
1731: action.setImageDescriptor(descriptor.getIcon());
1732: menu.appendToGroup(ITextEditorActionConstants.GROUP_RULERS,
1733: action);
1734: }
1735: }
1736:
1737: /**
1738: * Toggles the line number global preference and shows the line number ruler
1739: * accordingly.
1740: *
1741: * @since 3.1
1742: */
1743: private void toggleLineNumberRuler() {
1744: // globally
1745: IPreferenceStore store = EditorsUI.getPreferenceStore();
1746: store.setValue(LINE_NUMBER_RULER, !isLineNumberRulerVisible());
1747: }
1748:
1749: /**
1750: * Toggles the quick diff global preference and shows the quick diff ruler
1751: * accordingly.
1752: *
1753: * @since 3.1
1754: */
1755: private void toggleQuickDiffRuler() {
1756: // change the visibility locally if this editor is not in sync with the global preference
1757: // toggle the preference if we are in sync.
1758: IPreferenceStore store = EditorsUI.getPreferenceStore();
1759: boolean current = store
1760: .getBoolean(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON);
1761: if (current == isChangeInformationShowing())
1762: store
1763: .setValue(
1764: AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON,
1765: !current);
1766: else
1767: showChangeInformation(current);
1768: }
1769:
1770: /*
1771: * @see org.eclipse.ui.texteditor.AbstractTextEditor#editorContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager)
1772: * @since 3.1
1773: */
1774: protected void editorContextMenuAboutToShow(IMenuManager menu) {
1775: super .editorContextMenuAboutToShow(menu);
1776:
1777: IAction preferencesAction = getAction(ITextEditorActionConstants.CONTEXT_PREFERENCES);
1778: menu
1779: .appendToGroup(
1780: IWorkbenchActionConstants.MB_ADDITIONS,
1781: new Separator(
1782: ITextEditorActionConstants.GROUP_SETTINGS));
1783: menu.appendToGroup(ITextEditorActionConstants.GROUP_SETTINGS,
1784: preferencesAction);
1785:
1786: menu.appendToGroup(ITextEditorActionConstants.GROUP_SAVE,
1787: new Separator(ITextEditorActionConstants.GROUP_OPEN));
1788: MenuManager showInSubMenu = new MenuManager(
1789: getShowInMenuLabel());
1790: showInSubMenu.add(ContributionItemFactory.VIEWS_SHOW_IN
1791: .create(getEditorSite().getWorkbenchWindow()));
1792: menu.appendToGroup(ITextEditorActionConstants.GROUP_OPEN,
1793: showInSubMenu);
1794: }
1795:
1796: /**
1797: * Returns the menu label for 'Show In' together with its key binding string.
1798: *
1799: * @return the 'Show In' menu label
1800: * @since 3.2
1801: */
1802: private String getShowInMenuLabel() {
1803: String keyBinding = null;
1804:
1805: IBindingService bindingService = (IBindingService) PlatformUI
1806: .getWorkbench().getAdapter(IBindingService.class);
1807: if (bindingService != null)
1808: keyBinding = bindingService
1809: .getBestActiveBindingFormattedFor("org.eclipse.ui.navigate.showInQuickMenu"); //$NON-NLS-1$
1810:
1811: if (keyBinding == null)
1812: keyBinding = ""; //$NON-NLS-1$
1813:
1814: return NLS
1815: .bind(
1816: TextEditorMessages.AbstractDecoratedTextEditor_showIn_menu,
1817: keyBinding);
1818: }
1819:
1820: /**
1821: * Returns the preference page ids of the preference pages to be shown
1822: * when executing the preferences action from the editor context menu.
1823: * <p>
1824: * Subclasses may extend or replace.
1825: * </p>
1826: *
1827: * @return the preference page ids to show, may be empty
1828: * @since 3.1
1829: */
1830: protected String[] collectContextMenuPreferencePages() {
1831: return new String[] {
1832: "org.eclipse.ui.preferencePages.GeneralTextEditor", //$NON-NLS-1$
1833: "org.eclipse.ui.editors.preferencePages.Annotations", //$NON-NLS-1$
1834: "org.eclipse.ui.editors.preferencePages.QuickDiff", //$NON-NLS-1$
1835: "org.eclipse.ui.editors.preferencePages.Accessibility", //$NON-NLS-1$
1836: "org.eclipse.ui.editors.preferencePages.Spelling", //$NON-NLS-1$
1837: "org.eclipse.ui.editors.preferencePages.LinkedModePreferencePage", //$NON-NLS-1$
1838: };
1839: }
1840:
1841: /**
1842: * Returns the preference page ids of the preference pages to be shown when
1843: * executing the preferences action from the editor ruler context menu.
1844: * <p>
1845: * The default is to return the same list as
1846: * <code>collectContextMenuPreferencePages</code>.
1847: * </p>
1848: * <p>
1849: * Subclasses may extend or replace.
1850: * </p>
1851: *
1852: * @return the preference page ids to show, may be empty
1853: * @since 3.1
1854: */
1855: protected String[] collectRulerMenuPreferencePages() {
1856: return collectContextMenuPreferencePages();
1857: }
1858:
1859: /*
1860: * @see AbstractTextEditor#getUndoRedoOperationApprover(IUndoContext)
1861: * @since 3.1
1862: */
1863: protected IOperationApprover getUndoRedoOperationApprover(
1864: IUndoContext undoContext) {
1865: IEditorInput input = getEditorInput();
1866: if (input != null && input.getAdapter(IResource.class) != null)
1867: return new NonLocalUndoUserApprover(undoContext, this ,
1868: new Object[] { input }, IResource.class);
1869: return super .getUndoRedoOperationApprover(undoContext);
1870: }
1871:
1872: /**
1873: * Returns whether the given annotation is configured as a target for the
1874: * "Go to Next/Previous Annotation" actions.
1875: * <p>
1876: * The annotation is a target if their annotation type is configured to be
1877: * in the Next/Previous tool bar drop down menu and if it is checked.
1878: * </p>
1879: *
1880: * @param annotation the annotation
1881: * @return <code>true</code> if this is a target, <code>false</code> otherwise
1882: * @since 3.2
1883: */
1884: protected boolean isNavigationTarget(Annotation annotation) {
1885: AnnotationPreference preference = getAnnotationPreferenceLookup()
1886: .getAnnotationPreference(annotation);
1887: // See bug 41689
1888: // String key= forward ? preference.getIsGoToNextNavigationTargetKey() : preference.getIsGoToPreviousNavigationTargetKey();
1889: String key = preference == null ? null : preference
1890: .getIsGoToNextNavigationTargetKey();
1891: return (key != null && getPreferenceStore().getBoolean(key));
1892: }
1893:
1894: /**
1895: * {@inheritDoc}
1896: * <p>
1897: * This extended implementation updates views that also show the
1898: * select marker annotation.
1899: * </p>
1900: * @since 3.2
1901: */
1902: public Annotation gotoAnnotation(boolean forward) {
1903: Annotation annotation = super .gotoAnnotation(forward);
1904: if (annotation != null)
1905: updateMarkerViews(annotation);
1906: return annotation;
1907: }
1908:
1909: /**
1910: * Updates visible views that show markers.
1911: * <p>
1912: * If the given annotation can be associated with a marker then
1913: * this method tries select the this marker in views that show
1914: * markers.
1915: * </p>
1916: * @param annotation
1917: * @since 3.2
1918: */
1919: protected void updateMarkerViews(Annotation annotation) {
1920: IMarker marker = null;
1921: if (annotation instanceof MarkerAnnotation)
1922: marker = ((MarkerAnnotation) annotation).getMarker();
1923:
1924: if (marker != null) {
1925: try {
1926: fIsUpdatingMarkerViews = true;
1927: IWorkbenchPage page = getSite().getPage();
1928: MarkerViewUtil.showMarker(page, marker, false);
1929: } finally {
1930: fIsUpdatingMarkerViews = false;
1931: }
1932: }
1933: }
1934:
1935: /*
1936: * @see org.eclipse.ui.texteditor.AbstractTextEditor#isTabConversionEnabled()
1937: * @since 3.3
1938: */
1939: protected boolean isTabsToSpacesConversionEnabled() {
1940: return getPreferenceStore() != null
1941: && getPreferenceStore()
1942: .getBoolean(
1943: AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS);
1944: }
1945: }
|