KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > texteditor > AbstractDecoratedTextEditor


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.texteditor;
12
13 import java.io.File JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16
17 import com.ibm.icu.text.MessageFormat;
18
19 import org.eclipse.osgi.util.NLS;
20
21 import org.eclipse.swt.SWT;
22 import org.eclipse.swt.graphics.Color;
23 import org.eclipse.swt.layout.GridData;
24 import org.eclipse.swt.layout.GridLayout;
25 import org.eclipse.swt.widgets.Composite;
26 import org.eclipse.swt.widgets.Control;
27 import org.eclipse.swt.widgets.Display;
28 import org.eclipse.swt.widgets.FileDialog;
29 import org.eclipse.swt.widgets.Shell;
30
31 import org.eclipse.core.commands.operations.IOperationApprover;
32 import org.eclipse.core.commands.operations.IUndoContext;
33 import org.eclipse.core.filesystem.EFS;
34 import org.eclipse.core.filesystem.IFileStore;
35 import org.eclipse.core.filesystem.URIUtil;
36
37 import org.eclipse.core.runtime.CoreException;
38 import org.eclipse.core.runtime.IPath;
39 import org.eclipse.core.runtime.IProgressMonitor;
40 import org.eclipse.core.runtime.IStatus;
41
42 import org.eclipse.core.resources.IFile;
43 import org.eclipse.core.resources.IMarker;
44 import org.eclipse.core.resources.IResource;
45 import org.eclipse.core.resources.IResourceStatus;
46 import org.eclipse.core.resources.IWorkspace;
47 import org.eclipse.core.resources.IWorkspaceRoot;
48 import org.eclipse.core.resources.ResourcesPlugin;
49
50 import org.eclipse.core.filebuffers.FileBuffers;
51 import org.eclipse.core.filebuffers.IFileBufferStatusCodes;
52
53 import org.eclipse.jface.action.Action;
54 import org.eclipse.jface.action.GroupMarker;
55 import org.eclipse.jface.action.IAction;
56 import org.eclipse.jface.action.IMenuManager;
57 import org.eclipse.jface.action.MenuManager;
58 import org.eclipse.jface.action.Separator;
59 import org.eclipse.jface.dialogs.IDialogConstants;
60 import org.eclipse.jface.dialogs.IMessageProvider;
61 import org.eclipse.jface.dialogs.MessageDialog;
62 import org.eclipse.jface.dialogs.MessageDialogWithToggle;
63 import org.eclipse.jface.preference.IPreferenceStore;
64 import org.eclipse.jface.util.PropertyChangeEvent;
65 import org.eclipse.jface.viewers.ISelection;
66 import org.eclipse.jface.viewers.ISelectionProvider;
67 import org.eclipse.jface.window.Window;
68
69 import org.eclipse.jface.text.BadLocationException;
70 import org.eclipse.jface.text.IDocument;
71 import org.eclipse.jface.text.ITextViewerExtension6;
72 import org.eclipse.jface.text.Position;
73 import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
74 import org.eclipse.jface.text.revisions.IRevisionRulerColumn;
75 import org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension;
76 import org.eclipse.jface.text.revisions.RevisionInformation;
77 import org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension.RenderingMode;
78 import org.eclipse.jface.text.source.Annotation;
79 import org.eclipse.jface.text.source.AnnotationRulerColumn;
80 import org.eclipse.jface.text.source.ChangeRulerColumn;
81 import org.eclipse.jface.text.source.CompositeRuler;
82 import org.eclipse.jface.text.source.IAnnotationAccess;
83 import org.eclipse.jface.text.source.IAnnotationAccessExtension2;
84 import org.eclipse.jface.text.source.IAnnotationModel;
85 import org.eclipse.jface.text.source.IChangeRulerColumn;
86 import org.eclipse.jface.text.source.IOverviewRuler;
87 import org.eclipse.jface.text.source.ISharedTextColors;
88 import org.eclipse.jface.text.source.ISourceViewer;
89 import org.eclipse.jface.text.source.ISourceViewerExtension;
90 import org.eclipse.jface.text.source.ISourceViewerExtension3;
91 import org.eclipse.jface.text.source.IVerticalRuler;
92 import org.eclipse.jface.text.source.IVerticalRulerColumn;
93 import org.eclipse.jface.text.source.LineChangeHover;
94 import org.eclipse.jface.text.source.LineNumberChangeRulerColumn;
95 import org.eclipse.jface.text.source.LineNumberRulerColumn;
96 import org.eclipse.jface.text.source.OverviewRuler;
97 import org.eclipse.jface.text.source.SourceViewer;
98
99 import org.eclipse.ui.editors.text.DefaultEncodingSupport;
100 import org.eclipse.ui.editors.text.EditorsUI;
101 import org.eclipse.ui.editors.text.ForwardingDocumentProvider;
102 import org.eclipse.ui.editors.text.IEncodingSupport;
103 import org.eclipse.ui.editors.text.ITextEditorHelpContextIds;
104
105 import org.eclipse.ui.IEditorInput;
106 import org.eclipse.ui.IFileEditorInput;
107 import org.eclipse.ui.IURIEditorInput;
108 import org.eclipse.ui.IWorkbenchActionConstants;
109 import org.eclipse.ui.IWorkbenchPage;
110 import org.eclipse.ui.PlatformUI;
111 import org.eclipse.ui.actions.ActionFactory;
112 import org.eclipse.ui.actions.ContributionItemFactory;
113 import org.eclipse.ui.dialogs.PreferencesUtil;
114 import org.eclipse.ui.dialogs.SaveAsDialog;
115 import org.eclipse.ui.ide.FileStoreEditorInput;
116 import org.eclipse.ui.ide.IDEActionFactory;
117 import org.eclipse.ui.ide.IGotoMarker;
118 import org.eclipse.ui.internal.editors.quickdiff.CompositeRevertAction;
119 import org.eclipse.ui.internal.editors.quickdiff.RestoreAction;
120 import org.eclipse.ui.internal.editors.quickdiff.RevertBlockAction;
121 import org.eclipse.ui.internal.editors.quickdiff.RevertLineAction;
122 import org.eclipse.ui.internal.editors.quickdiff.RevertSelectionAction;
123 import org.eclipse.ui.internal.editors.text.EditorsPlugin;
124 import org.eclipse.ui.internal.editors.text.NLSUtility;
125 import org.eclipse.ui.internal.editors.text.RefreshEditorAction;
126 import org.eclipse.ui.internal.texteditor.AnnotationColumn;
127 import org.eclipse.ui.internal.texteditor.BooleanPreferenceToggleAction;
128 import org.eclipse.ui.internal.texteditor.LineNumberColumn;
129 import org.eclipse.ui.internal.texteditor.TextChangeHover;
130 import org.eclipse.ui.keys.IBindingService;
131 import org.eclipse.ui.operations.NonLocalUndoUserApprover;
132 import org.eclipse.ui.part.FileEditorInput;
133 import org.eclipse.ui.part.IShowInSource;
134 import org.eclipse.ui.part.ShowInContext;
135 import org.eclipse.ui.texteditor.rulers.IColumnSupport;
136 import org.eclipse.ui.texteditor.rulers.IContributedRulerColumn;
137 import org.eclipse.ui.texteditor.rulers.RulerColumnDescriptor;
138 import org.eclipse.ui.texteditor.rulers.RulerColumnPreferenceAdapter;
139 import org.eclipse.ui.texteditor.rulers.RulerColumnRegistry;
140 import org.eclipse.ui.views.markers.MarkerViewUtil;
141
142 /**
143  * An intermediate editor comprising functionality not present in the leaner <code>AbstractTextEditor</code>,
144  * but used in many heavy weight (and especially source editing) editors, such as line numbers,
145  * change ruler, overview ruler, print margins, current line highlighting, etc.
146  *
147  * @since 3.0
148  */

149 public abstract class AbstractDecoratedTextEditor extends StatusTextEditor {
150
151     /**
152      * Preference key for showing the line number ruler.
153      */

154     private final static String JavaDoc LINE_NUMBER_RULER= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER;
155     /**
156      * Preference key for showing the overview ruler.
157      */

158     private final static String JavaDoc OVERVIEW_RULER= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_OVERVIEW_RULER;
159     /**
160      * Preference key for highlighting current line.
161      */

162     private final static String JavaDoc CURRENT_LINE= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE;
163     /**
164      * Preference key for highlight color of current line.
165      */

166     private final static String JavaDoc CURRENT_LINE_COLOR= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
167     /**
168      * Preference key for showing print margin ruler.
169      */

170     private final static String JavaDoc PRINT_MARGIN= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN;
171     /**
172      * Preference key for print margin ruler color.
173      */

174     private final static String JavaDoc PRINT_MARGIN_COLOR= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
175     /**
176      * Preference key for print margin ruler column.
177      */

178     private final static String JavaDoc PRINT_MARGIN_COLUMN= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
179     /**
180      * Preference key to get whether the overwrite mode is disabled.
181      * @since 3.1
182      */

183     private final static String JavaDoc DISABLE_OVERWRITE_MODE= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE;
184
185     /**
186      * Adapter class for <code>IGotoMarker</code>.
187      */

188     private class GotoMarkerAdapter implements IGotoMarker {
189         public void gotoMarker(IMarker marker) {
190             AbstractDecoratedTextEditor.this.gotoMarker(marker);
191         }
192     }
193
194     /**
195      * The annotation preferences.
196      */

197     private MarkerAnnotationPreferences fAnnotationPreferences;
198     /**
199      * The overview ruler of this editor.
200      *
201      * <p>This field should not be referenced by subclasses. It is <code>protected</code> for API
202      * compatibility reasons and will be made <code>private</code> soon. Use
203      * {@link #getOverviewRuler()} instead.</p>
204      */

205     protected IOverviewRuler fOverviewRuler;
206     /**
207      * Helper for accessing annotation from the perspective of this editor.
208      *
209      * <p>This field should not be referenced by subclasses. It is <code>protected</code> for API
210      * compatibility reasons and will be made <code>private</code> soon. Use
211      * {@link #getAnnotationAccess()} instead.</p>
212      */

213     protected IAnnotationAccess fAnnotationAccess;
214     /**
215      * Helper for managing the decoration support of this editor's viewer.
216      *
217      * <p>This field should not be referenced by subclasses. It is <code>protected</code> for API
218      * compatibility reasons and will be made <code>private</code> soon. Use
219      * {@link #getSourceViewerDecorationSupport(ISourceViewer)} instead.</p>
220      */

221     protected SourceViewerDecorationSupport fSourceViewerDecorationSupport;
222     /**
223      * The line number column.
224      *
225      * <p>This field should not be referenced by subclasses. It is <code>protected</code> for API
226      * compatibility reasons and will be made <code>private</code> soon. Use
227      * {@link AbstractTextEditor#getVerticalRuler()} to access the vertical bar instead.</p>
228      */

229     protected LineNumberRulerColumn fLineNumberRulerColumn;
230     /**
231      * The delegating line number ruler contribution.
232      * @since 3.3
233      */

234     private LineNumberColumn fLineColumn;
235     /**
236      * The editor's implicit document provider.
237      */

238     private IDocumentProvider fImplicitDocumentProvider;
239     /**
240      * The editor's goto marker adapter.
241      */

242     private Object JavaDoc fGotoMarkerAdapter= new GotoMarkerAdapter();
243     /**
244      * Indicates whether this editor is updating views that show markers.
245      * @see #updateMarkerViews(Annotation)
246      * @since 3.2
247      */

248     protected boolean fIsUpdatingMarkerViews= false;
249     /**
250      * Tells whether editing the current derived editor input is allowed.
251      * @since 3.3
252      */

253     private boolean fIsEditingDerivedFileAllowed= true;
254     /**
255      * Tells whether the derived state has been validated.
256      * @since 3.3
257      */

258     private boolean fIsDerivedStateValidated= false;
259
260     
261     /*
262      * Workaround for IllegalAccessError thrown because we are accessing
263      * a protected method in a different bundle from an inner class.
264      * @since 3.3
265      */

266     private IVerticalRuler internalGetVerticalRuler() {
267         return getVerticalRuler();
268     }
269     
270     /**
271      * Creates a new text editor.
272      */

273     public AbstractDecoratedTextEditor() {
274         super();
275         fAnnotationPreferences= EditorsPlugin.getDefault().getMarkerAnnotationPreferences();
276         setRangeIndicator(new DefaultRangeIndicator());
277         initializeKeyBindingScopes();
278         initializeEditor();
279     }
280
281     /**
282      * Initializes this editor. Subclasses may re-implement. If sub-classes do
283      * not change the contract, this method should not be extended, i.e. do not
284      * call <code>super.initializeEditor()</code> in order to avoid the
285      * temporary creation of objects that are immediately overwritten by
286      * subclasses.
287      */

288     protected void initializeEditor() {
289         setPreferenceStore(EditorsPlugin.getDefault().getPreferenceStore());
290     }
291
292     /**
293      * Initializes the key binding scopes of this editor.
294      */

295     protected void initializeKeyBindingScopes() {
296         setKeyBindingScopes(new String JavaDoc[] { "org.eclipse.ui.textEditorScope" }); //$NON-NLS-1$
297
}
298
299     /*
300      * @see IWorkbenchPart#dispose()
301      */

302     public void dispose() {
303         if (fSourceViewerDecorationSupport != null) {
304             fSourceViewerDecorationSupport.dispose();
305             fSourceViewerDecorationSupport= null;
306         }
307
308         fAnnotationAccess= null;
309         fAnnotationPreferences= null;
310         
311         fLineNumberRulerColumn= null;
312         fLineColumn= null;
313         
314         super.dispose();
315     }
316
317     /*
318      * @see org.eclipse.ui.texteditor.AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
319      */

320     protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
321
322         fAnnotationAccess= getAnnotationAccess();
323         fOverviewRuler= createOverviewRuler(getSharedColors());
324
325         ISourceViewer viewer= new SourceViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), styles);
326         // ensure decoration support has been created and configured.
327
getSourceViewerDecorationSupport(viewer);
328
329         return viewer;
330     }
331
332     protected ISharedTextColors getSharedColors() {
333         ISharedTextColors sharedColors= EditorsPlugin.getDefault().getSharedTextColors();
334         return sharedColors;
335     }
336
337     protected IOverviewRuler createOverviewRuler(ISharedTextColors sharedColors) {
338         IOverviewRuler ruler= new OverviewRuler(getAnnotationAccess(), VERTICAL_RULER_WIDTH, sharedColors);
339         Iterator JavaDoc e= fAnnotationPreferences.getAnnotationPreferences().iterator();
340         while (e.hasNext()) {
341             AnnotationPreference preference= (AnnotationPreference) e.next();
342             if (preference.contributesToHeader())
343                 ruler.addHeaderAnnotationType(preference.getAnnotationType());
344         }
345         return ruler;
346     }
347
348     /**
349      * Creates the annotation access for this editor.
350      *
351      * @return the created annotation access
352      */

353     protected IAnnotationAccess createAnnotationAccess() {
354         return new DefaultMarkerAnnotationAccess();
355     }
356
357     /**
358      * Configures the decoration support for this editor's source viewer. Subclasses may override this
359      * method, but should call their superclass' implementation at some point.
360      *
361      * @param support the decoration support to configure
362      */

363     protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) {
364
365         Iterator JavaDoc e= fAnnotationPreferences.getAnnotationPreferences().iterator();
366         while (e.hasNext())
367             support.setAnnotationPreference((AnnotationPreference) e.next());
368
369         support.setCursorLinePainterPreferenceKeys(CURRENT_LINE, CURRENT_LINE_COLOR);
370         support.setMarginPainterPreferenceKeys(PRINT_MARGIN, PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN);
371         support.setSymbolicFontName(getFontPropertyPreferenceKey());
372     }
373
374     /*
375      * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
376      */

377     public void createPartControl(Composite parent) {
378         super.createPartControl(parent);
379         if (fSourceViewerDecorationSupport != null)
380             fSourceViewerDecorationSupport.install(getPreferenceStore());
381
382         IColumnSupport columnSupport= (IColumnSupport)getAdapter(IColumnSupport.class);
383         
384         if (isLineNumberRulerVisible()) {
385             RulerColumnDescriptor lineNumberColumnDescriptor= RulerColumnRegistry.getDefault().getColumnDescriptor(LineNumberColumn.ID);
386             if (lineNumberColumnDescriptor != null)
387                 columnSupport.setColumnVisible(lineNumberColumnDescriptor, true);
388         }
389
390         if (isPrefQuickDiffAlwaysOn())
391             showChangeInformation(true);
392
393         if (!isOverwriteModeEnabled())
394             enableOverwriteMode(false);
395
396         if (!isRangeIndicatorEnabled()) {
397             getSourceViewer().removeRangeIndication();
398             getSourceViewer().setRangeIndicator(null);
399         }
400
401         // Assign the quick assist assistant to the annotation access.
402
ISourceViewer viewer= getSourceViewer();
403         if (fAnnotationAccess instanceof IAnnotationAccessExtension2 && viewer instanceof ISourceViewerExtension3)
404             ((IAnnotationAccessExtension2)fAnnotationAccess).setQuickAssistAssistant(((ISourceViewerExtension3)viewer).getQuickAssistAssistant());
405     }
406
407     /*
408      * @see org.eclipse.ui.texteditor.StatusTextEditor#createStatusControl(org.eclipse.swt.widgets.Composite, org.eclipse.core.runtime.IStatus)
409      * @since 3.1
410      */

411     protected Control createStatusControl(Composite parent, final IStatus status) {
412         Object JavaDoc adapter= getAdapter(IEncodingSupport.class);
413         DefaultEncodingSupport encodingSupport= null;
414         if (adapter instanceof DefaultEncodingSupport)
415             encodingSupport= (DefaultEncodingSupport)adapter;
416
417         if (encodingSupport == null || !encodingSupport.isEncodingError(status))
418             return super.createStatusControl(parent, status);
419
420         Shell shell= getSite().getShell();
421         Display display= shell.getDisplay();
422         Color bgColor= display.getSystemColor(SWT.COLOR_LIST_BACKGROUND);
423         Color fgColor= display.getSystemColor(SWT.COLOR_LIST_FOREGROUND);
424
425         Composite composite= new Composite(parent, SWT.NONE);
426         composite.setLayout(new GridLayout());
427         composite.setBackground(bgColor);
428         composite.setForeground(fgColor);
429
430         Control control= super.createStatusControl(composite, status);
431         control.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
432
433         Composite buttonComposite= new Composite(composite, SWT.NONE);
434         buttonComposite.setLayout(new GridLayout());
435         buttonComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
436         buttonComposite.setBackground(bgColor);
437         buttonComposite.setForeground(fgColor);
438
439         encodingSupport.createStatusEncodingChangeControl(buttonComposite, status);
440 //
441
// Button button= new Button(buttonComposite, SWT.PUSH | SWT.FLAT);
442
// button.setText(action.getText());
443
// button.addSelectionListener(new SelectionAdapter() {
444
// /*
445
// * @see org.eclipse.swt.events.SelectionAdapter#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
446
// */
447
// public void widgetSelected(SelectionEvent e) {
448
// action.run();
449
// }
450
// });
451
//
452
// Label filler= new Label(buttonComposite, SWT.NONE);
453
// filler.setLayoutData(new GridData(GridData.FILL_BOTH));
454
// filler.setBackground(bgColor);
455
//
456
return composite;
457     }
458
459     /**
460      * Tells whether the overview ruler is visible.
461      *
462      * @return whether the overview ruler is visible
463      */

464     protected boolean isOverviewRulerVisible() {
465         IPreferenceStore store= getPreferenceStore();
466         return store != null ? store.getBoolean(OVERVIEW_RULER) : false;
467     }
468
469     /*
470      * @see org.eclipse.ui.texteditor.ITextEditorExtension3#showChangeInformation(boolean)
471      */

472     public void showChangeInformation(boolean show) {
473         if (show == isChangeInformationShowing())
474             return;
475
476         IColumnSupport columnSupport= (IColumnSupport)getAdapter(IColumnSupport.class);
477         
478         // only handle visibility of the combined column, but not the number/change only state
479
if (show && fLineColumn == null) {
480             RulerColumnDescriptor lineNumberColumnDescriptor= RulerColumnRegistry.getDefault().getColumnDescriptor(LineNumberColumn.ID);
481             if (lineNumberColumnDescriptor != null)
482                 columnSupport.setColumnVisible(lineNumberColumnDescriptor, true);
483         } else if (!show && fLineColumn != null && !isLineNumberRulerVisible()) {
484             columnSupport.setColumnVisible(fLineColumn.getDescriptor(), false);
485             fLineColumn= null;
486         }
487     }
488     
489     /*
490      * @see org.eclipse.ui.texteditor.ITextEditorExtension3#isChangeInformationShowing()
491      */

492     public boolean isChangeInformationShowing() {
493         return fLineColumn != null && fLineColumn.isShowingChangeInformation();
494     }
495     
496     /*
497      * @see org.eclipse.ui.texteditor.ITextEditorExtension4#showRevisionInformation(org.eclipse.jface.text.revisions.RevisionInformation, java.lang.String)
498      * @since 3.2
499      */

500     public void showRevisionInformation(RevisionInformation info, String JavaDoc quickDiffProviderId) {
501         if (info.getHoverControlCreator() == null)
502             info.setHoverControlCreator(new RevisionHoverInformationControlCreator(false));
503         
504         showChangeInformation(true);
505         if (fLineColumn != null)
506             fLineColumn.showRevisionInformation(info, quickDiffProviderId);
507     }
508
509     /**
510      * Returns whether the line number ruler column should be
511      * visible according to the preference store settings. Subclasses may override this
512      * method to provide a custom preference setting.
513      *
514      * @return <code>true</code> if the line numbers should be visible
515      */

516     protected boolean isLineNumberRulerVisible() {
517         IPreferenceStore store= getPreferenceStore();
518         return store != null ? store.getBoolean(LINE_NUMBER_RULER) : false;
519     }
520
521     /**
522      * Returns whether the overwrite mode is enabled according to the preference
523      * store settings. Subclasses may override this method to provide a custom
524      * preference setting.
525      *
526      * @return <code>true</code> if overwrite mode is enabled
527      * @since 3.1
528      */

529     protected boolean isOverwriteModeEnabled() {
530         IPreferenceStore store= getPreferenceStore();
531         return store != null ? !store.getBoolean(DISABLE_OVERWRITE_MODE) : true;
532     }
533
534     /**
535      * Returns whether the range indicator is enabled according to the preference
536      * store settings. Subclasses may override this method to provide a custom
537      * preference setting.
538      *
539      * @return <code>true</code> if overwrite mode is enabled
540      * @since 3.1
541      */

542     private boolean isRangeIndicatorEnabled() {
543         IPreferenceStore store= getPreferenceStore();
544         return store != null ? store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.SHOW_RANGE_INDICATOR) : true;
545     }
546     
547     /**
548      * Returns whether quick diff info should be visible upon opening an editor
549      * according to the preference store settings.
550      *
551      * @return <code>true</code> if the line numbers should be visible
552      */

553     protected boolean isPrefQuickDiffAlwaysOn() {
554         IPreferenceStore store= getPreferenceStore();
555         boolean setting= store != null ? store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON) : false;
556         return setting && isEditorInputModifiable();
557     }
558
559     /**
560      * Initializes the given line number ruler column from the preference store.
561      *
562      * @param rulerColumn the ruler column to be initialized
563      */

564     protected void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) {
565         /*
566          * Left for compatibility. See LineNumberColumn.
567          */

568         if (fLineColumn != null)
569             fLineColumn.initializeLineNumberRulerColumn(rulerColumn);
570     }
571
572     /**
573      * Creates a new line number ruler column that is appropriately initialized.
574      *
575      * @return the created line number column
576      */

577     protected IVerticalRulerColumn createLineNumberRulerColumn() {
578         /*
579          * Left for compatibility. See LineNumberColumn.
580          */

581         fLineNumberRulerColumn= new LineNumberChangeRulerColumn(getSharedColors());
582         ((IChangeRulerColumn) fLineNumberRulerColumn).setHover(createChangeHover());
583         initializeLineNumberRulerColumn(fLineNumberRulerColumn);
584         return fLineNumberRulerColumn;
585     }
586
587     /**
588      * Creates and returns a <code>LineChangeHover</code> to be used on this editor's change
589      * ruler column. This default implementation returns a plain <code>LineChangeHover</code>.
590      * Subclasses may override.
591      *
592      * @return the change hover to be used by this editors quick diff display
593      */

594     protected LineChangeHover createChangeHover() {
595         return new TextChangeHover();
596     }
597
598     /**
599      * Creates a new change ruler column for quick diff display independent of the
600      * line number ruler column
601      *
602      * @return a new change ruler column
603      * @deprecated as of 3.3. Not called any longer, replaced by {@link #createLineNumberRulerColumn()}
604      */

605     protected IChangeRulerColumn createChangeRulerColumn() {
606         /*
607          * Left for compatibility. See LineNumberColumn.
608          */

609         return new ChangeRulerColumn(getSharedColors());
610     }
611
612     /**
613      * Returns {@link #createCompositeRuler()}. Subclasses should not override this method, but
614      * rather <code>createCompositeRuler</code> if they want to contribute their own vertical ruler
615      * implementation. If not an instance of {@link CompositeRuler} is returned, the built-in ruler
616      * columns (line numbers, annotations) will not work.
617      *
618      * <p>May become <code>final</code> in the future.</p>
619      *
620      * @see AbstractTextEditor#createVerticalRuler()
621      */

622     protected IVerticalRuler createVerticalRuler() {
623         return createCompositeRuler();
624     }
625     
626
627     /**
628      * Creates a composite ruler to be used as the vertical ruler by this editor.
629      * Subclasses may re-implement this method.
630      *
631      * @return the vertical ruler
632      */

633     protected CompositeRuler createCompositeRuler() {
634         return new CompositeRuler();
635     }
636
637     
638     /**
639      * Creates the annotation ruler column. Subclasses may re-implement or extend.
640      *
641      * @param ruler the composite ruler that the column will be added
642      * @return an annotation ruler column
643      * @since 3.2
644      */

645     protected IVerticalRulerColumn createAnnotationRulerColumn(CompositeRuler ruler) {
646         return new AnnotationRulerColumn(VERTICAL_RULER_WIDTH, getAnnotationAccess());
647     }
648
649     /*
650      * @see org.eclipse.ui.texteditor.AbstractTextEditor#createColumnSupport()
651      * @since 3.3
652      */

653     protected final IColumnSupport createColumnSupport() {
654         return new ColumnSupport(this, RulerColumnRegistry.getDefault()) {
655             /*
656              * @see org.eclipse.ui.texteditor.rulers.ColumnSupport#initializeColumn(org.eclipse.ui.texteditor.rulers.AbstractContributedRulerColumn)
657              */

658             protected void initializeColumn(IContributedRulerColumn column) {
659                 super.initializeColumn(column);
660                 RulerColumnDescriptor descriptor= column.getDescriptor();
661                 IVerticalRuler ruler= internalGetVerticalRuler();
662                 if (ruler instanceof CompositeRuler) {
663                     if (AnnotationColumn.ID.equals(descriptor.getId())) {
664                         ((AnnotationColumn)column).setDelegate(createAnnotationRulerColumn((CompositeRuler) ruler));
665                     } else if (LineNumberColumn.ID.equals(descriptor.getId())) {
666                         fLineColumn= ((LineNumberColumn) column);
667                         fLineColumn.setForwarder(new LineNumberColumn.ICompatibilityForwarder() {
668                             public IVerticalRulerColumn createLineNumberRulerColumn() {
669                                 return AbstractDecoratedTextEditor.this.createLineNumberRulerColumn();
670                             }
671                             public boolean isQuickDiffEnabled() {
672                                 return AbstractDecoratedTextEditor.this.isPrefQuickDiffAlwaysOn();
673                             }
674                             public boolean isLineNumberRulerVisible() {
675                                 return AbstractDecoratedTextEditor.this.isLineNumberRulerVisible();
676                             }
677                         });
678                     }
679                 }
680             }
681
682             /*
683              * @see org.eclipse.ui.texteditor.AbstractTextEditor.ColumnSupport#dispose()
684              */

685             public void dispose() {
686                 fLineColumn= null;
687                 super.dispose();
688             }
689         };
690     }
691
692     /*
693      * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
694      */

695     protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
696
697         try {
698
699             ISourceViewer sourceViewer= getSourceViewer();
700             if (sourceViewer == null)
701                 return;
702
703             String JavaDoc property= event.getProperty();
704
705             if (fSourceViewerDecorationSupport != null && fOverviewRuler != null && OVERVIEW_RULER.equals(property)) {
706                 if (isOverviewRulerVisible())
707                     showOverviewRuler();
708                 else
709                     hideOverviewRuler();
710                 return;
711             }
712
713             if (DISABLE_OVERWRITE_MODE.equals(property)) {
714                 enableOverwriteMode(isOverwriteModeEnabled());
715                 return;
716             }
717
718             if (LINE_NUMBER_RULER.equals(property)) {
719                 // only handle visibility of the combined column, but not the number/change only state
720
IColumnSupport columnSupport= (IColumnSupport)getAdapter(IColumnSupport.class);
721                 if (isLineNumberRulerVisible() && fLineColumn == null) {
722                     RulerColumnDescriptor lineNumberColumnDescriptor= RulerColumnRegistry.getDefault().getColumnDescriptor(LineNumberColumn.ID);
723                     if (lineNumberColumnDescriptor != null)
724                         columnSupport.setColumnVisible(lineNumberColumnDescriptor, true);
725                 } else if (!isLineNumberRulerVisible() && fLineColumn != null && !fLineColumn.isShowingChangeInformation()) {
726                     columnSupport.setColumnVisible(fLineColumn.getDescriptor(), false);
727                     fLineColumn= null;
728                 }
729                 return;
730             }
731
732             if (AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON.equals(property)) {
733                 showChangeInformation(isPrefQuickDiffAlwaysOn());
734             }
735
736             if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) {
737                 IPreferenceStore store= getPreferenceStore();
738                 if (store != null)
739                     sourceViewer.getTextWidget().setTabs(store.getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH));
740                 if (isTabsToSpacesConversionEnabled()) {
741                     uninstallTabsToSpacesConverter();
742                     installTabsToSpacesConverter();
743                 }
744                 return;
745             }
746             
747             if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS.equals(property)) {
748                 if (isTabsToSpacesConversionEnabled())
749                     installTabsToSpacesConverter();
750                 else
751                     uninstallTabsToSpacesConverter();
752                 return;
753             }
754
755             if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_UNDO_HISTORY_SIZE.equals(property) && sourceViewer instanceof ITextViewerExtension6) {
756                 IPreferenceStore store= getPreferenceStore();
757                 if (store != null)
758                     ((ITextViewerExtension6)sourceViewer).getUndoManager().setMaximalUndoLevel(store.getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_UNDO_HISTORY_SIZE));
759                 return;
760             }
761
762             if (AbstractDecoratedTextEditorPreferenceConstants.SHOW_RANGE_INDICATOR.equals(property)) {
763                 if (isRangeIndicatorEnabled()) {
764                     getSourceViewer().setRangeIndicator(getRangeIndicator());
765                 } else {
766                     getSourceViewer().removeRangeIndication();
767                     getSourceViewer().setRangeIndicator(null);
768                 }
769             }
770
771             if (sourceViewer instanceof ITextViewerExtension6) {
772                 HyperlinkDetectorDescriptor[] descriptor= EditorsUI.getHyperlinkDetectorRegistry().getHyperlinkDetectorDescriptors();
773                 for (int i= 0; i < descriptor.length; i++) {
774                     if (descriptor[i].getId().equals(property) || (descriptor[i].getId() + HyperlinkDetectorDescriptor.STATE_MASK_POSTFIX).equals(property)) {
775                         IHyperlinkDetector[] detectors= getSourceViewerConfiguration().getHyperlinkDetectors(sourceViewer);
776                         int stateMask= getSourceViewerConfiguration().getHyperlinkStateMask(sourceViewer);
777                         ITextViewerExtension6 textViewer6= (ITextViewerExtension6)sourceViewer;
778                         textViewer6.setHyperlinkDetectors(detectors, stateMask);
779                         return;
780                     }
781                 }
782             }
783
784         } finally {
785             super.handlePreferenceStoreChanged(event);
786         }
787     }
788
789     /**
790      * Shows the overview ruler.
791      */

792     protected void showOverviewRuler() {
793         if (fOverviewRuler != null) {
794             if (getSourceViewer() instanceof ISourceViewerExtension) {
795                 ((ISourceViewerExtension) getSourceViewer()).showAnnotationsOverview(true);
796                 fSourceViewerDecorationSupport.updateOverviewDecorations();
797             }
798         }
799     }
800
801     /**
802      * Hides the overview ruler.
803      */

804     protected void hideOverviewRuler() {
805         if (getSourceViewer() instanceof ISourceViewerExtension) {
806             fSourceViewerDecorationSupport.hideAnnotationOverview();
807             ((ISourceViewerExtension) getSourceViewer()).showAnnotationsOverview(false);
808         }
809     }
810
811     /**
812      * Returns the annotation access.
813      *
814      * @return the annotation access
815      */

816     protected IAnnotationAccess getAnnotationAccess() {
817         if (fAnnotationAccess == null)
818             fAnnotationAccess= createAnnotationAccess();
819         return fAnnotationAccess;
820     }
821
822     /**
823      * Returns the annotation preference lookup.
824      *
825      * @return the annotation preference lookup
826      */

827     protected AnnotationPreferenceLookup getAnnotationPreferenceLookup() {
828         return EditorsPlugin.getDefault().getAnnotationPreferenceLookup();
829     }
830
831     /**
832      * Returns the overview ruler.
833      *
834      * @return the overview ruler
835      */

836     protected IOverviewRuler getOverviewRuler() {
837         if (fOverviewRuler == null)
838             fOverviewRuler= createOverviewRuler(getSharedColors());
839         return fOverviewRuler;
840     }
841
842     /**
843      * Returns the source viewer decoration support.
844      *
845      * @param viewer the viewer for which to return a decoration support
846      * @return the source viewer decoration support
847      */

848     protected SourceViewerDecorationSupport getSourceViewerDecorationSupport(ISourceViewer viewer) {
849         if (fSourceViewerDecorationSupport == null) {
850             fSourceViewerDecorationSupport= new SourceViewerDecorationSupport(viewer, getOverviewRuler(), getAnnotationAccess(), getSharedColors());
851             configureSourceViewerDecorationSupport(fSourceViewerDecorationSupport);
852         }
853         return fSourceViewerDecorationSupport;
854     }
855
856     /**
857      * Returns the annotation preferences.
858      *
859      * @return the annotation preferences
860      */

861     protected MarkerAnnotationPreferences getAnnotationPreferences() {
862         return fAnnotationPreferences;
863     }
864
865
866     /**
867      * If the editor can be saved all marker ranges have been changed according to
868      * the text manipulations. However, those changes are not yet propagated to the
869      * marker manager. Thus, when opening a marker, the marker's position in the editor
870      * must be determined as it might differ from the position stated in the marker.
871      *
872      * @param marker the marker to go to
873      * @deprecated visibility will be reduced, use <code>getAdapter(IGotoMarker.class) for accessing this method</code>
874      */

875     public void gotoMarker(IMarker marker) {
876         if (fIsUpdatingMarkerViews)
877             return;
878         
879         if (getSourceViewer() == null)
880             return;
881
882         int start= MarkerUtilities.getCharStart(marker);
883         int end= MarkerUtilities.getCharEnd(marker);
884         
885         boolean selectLine= start < 0 || end < 0;
886
887         // look up the current range of the marker when the document has been edited
888
IAnnotationModel model= getDocumentProvider().getAnnotationModel(getEditorInput());
889         if (model instanceof AbstractMarkerAnnotationModel) {
890
891             AbstractMarkerAnnotationModel markerModel= (AbstractMarkerAnnotationModel) model;
892             Position pos= markerModel.getMarkerPosition(marker);
893             if (pos != null && !pos.isDeleted()) {
894                 // use position instead of marker values
895
start= pos.getOffset();
896                 end= pos.getOffset() + pos.getLength();
897             }
898
899             if (pos != null && pos.isDeleted()) {
900                 // do nothing if position has been deleted
901
return;
902             }
903         }
904
905         IDocument document= getDocumentProvider().getDocument(getEditorInput());
906
907         if (selectLine) {
908             int line;
909             try {
910                 if (start >= 0)
911                     line= document.getLineOfOffset(start);
912                 else {
913                     line= MarkerUtilities.getLineNumber(marker);
914                     // Marker line numbers are 1-based
915
-- line;
916                     start= document.getLineOffset(line);
917                 }
918                 end= start + document.getLineLength(line) - 1;
919             } catch (BadLocationException e) {
920                 return;
921             }
922         }
923
924         int length= document.getLength();
925         if (end - 1 < length && start < length)
926             selectAndReveal(start, end - start);
927     }
928     
929     /*
930      * @see org.eclipse.ui.texteditor.AbstractTextEditor#isEditable()
931      * @since 3.3
932      */

933     public boolean isEditable() {
934         if (!super.isEditable())
935             return false;
936         return fIsEditingDerivedFileAllowed;
937     }
938
939     /*
940      * @see org.eclipse.ui.texteditor.StatusTextEditor#validateEditorInputState()
941      * @since 3.3
942      */

943     public boolean validateEditorInputState() {
944         if (!super.validateEditorInputState())
945             return false;
946
947         return validateEditorInputDerived();
948     }
949
950     /**
951      * Validates the editor input for derived state.
952      * If the given input is derived then this method
953      * can show a dialog asking whether to edit the
954      * derived file.
955      *
956      * @return <code>true</code> if the input is OK for editing, <code>false</code> otherwise
957      * @since 3.3
958      */

959     private boolean validateEditorInputDerived() {
960         if (fIsDerivedStateValidated)
961             return fIsEditingDerivedFileAllowed;
962
963         if (getDocumentProvider() instanceof IDocumentProviderExtension) {
964             IDocumentProviderExtension extension= (IDocumentProviderExtension)getDocumentProvider();
965             IStatus status= extension.getStatus(getEditorInput());
966             String JavaDoc pluginId= status.getPlugin();
967             boolean isDerivedStatus= status.getCode() == IFileBufferStatusCodes.DERIVED_FILE && (FileBuffers.PLUGIN_ID.equals(pluginId) || EditorsUI.PLUGIN_ID.equals(pluginId));
968             if (!isDerivedStatus)
969                 return true;
970         }
971
972         final String JavaDoc warnKey= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_WARN_IF_INPUT_DERIVED;
973         IPreferenceStore store= getPreferenceStore();
974         if (!store.getBoolean(warnKey))
975             return true;
976         
977         MessageDialogWithToggle toggleDialog= MessageDialogWithToggle.openYesNoQuestion(
978                 getSite().getShell(),
979                 TextEditorMessages.AbstractDecoratedTextEditor_warning_derived_title,
980                 TextEditorMessages.AbstractDecoratedTextEditor_warning_derived_message,
981                 TextEditorMessages.AbstractDecoratedTextEditor_warning_derived_dontShowAgain,
982                 false,
983                 null,
984                 null);
985         
986         EditorsUI.getPreferenceStore().setValue(warnKey, !toggleDialog.getToggleState());
987         fIsDerivedStateValidated= true;
988         return fIsEditingDerivedFileAllowed= toggleDialog.getReturnCode() == IDialogConstants.YES_ID;
989     }
990
991     /*
992      * For an explanation why we override this method see:
993      * bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=42230
994      *
995      * @see org.eclipse.ui.texteditor.StatusTextEditor#isErrorStatus(org.eclipse.core.runtime.IStatus)
996      */

997     protected boolean isErrorStatus(IStatus status) {
998         if (!super.isErrorStatus(status))
999             return false;
1000        
1001        if (!status.isMultiStatus())
1002            return !isReadOnlyLocalStatus(status);
1003        
1004        IStatus[] childrenStatus= status.getChildren();
1005        for (int i= 0; i < childrenStatus.length; i++) {
1006            if (childrenStatus[i].getSeverity() == IStatus.ERROR && !isReadOnlyLocalStatus(childrenStatus[i]))
1007                return true;
1008        }
1009        
1010        return false;
1011    }
1012
1013    /**
1014     * Check whether the given status is a <code>IResourceStatus.READ_ONLY_LOCAL</code>
1015     * error.
1016     *
1017     * @param status the status to be checked
1018     * @return <code>true</code> if the given status is a <code>IResourceStatus.READ_ONLY_LOCAL</code> error
1019     * @since 3.3
1020     */

1021    private boolean isReadOnlyLocalStatus(IStatus status) {
1022        return status.getCode() == IResourceStatus.READ_ONLY_LOCAL;
1023    }
1024
1025    /*
1026     * @see org.eclipse.ui.texteditor.AbstractTextEditor#createActions()
1027     */

1028    protected void createActions() {
1029        super.createActions();
1030
1031        ResourceAction action= new AddMarkerAction(TextEditorMessages.getBundleForConstructedKeys(), "Editor.AddBookmark.", this, IMarker.BOOKMARK, true); //$NON-NLS-1$
1032
action.setHelpContextId(ITextEditorHelpContextIds.BOOKMARK_ACTION);
1033        action.setActionDefinitionId(IWorkbenchActionDefinitionIds.ADD_BOOKMARK);
1034        setAction(IDEActionFactory.BOOKMARK.getId(), action);
1035
1036        action= new AddTaskAction(TextEditorMessages.getBundleForConstructedKeys(), "Editor.AddTask.", this); //$NON-NLS-1$
1037
action.setHelpContextId(ITextEditorHelpContextIds.ADD_TASK_ACTION);
1038        action.setActionDefinitionId(IWorkbenchActionDefinitionIds.ADD_TASK);
1039        setAction(IDEActionFactory.ADD_TASK.getId(), action);
1040
1041        action= new ChangeEncodingAction(TextEditorMessages.getBundleForConstructedKeys(), "Editor.ChangeEncodingAction.", this); //$NON-NLS-1$
1042
action.setHelpContextId(ITextEditorHelpContextIds.CHANGE_ENCODING);
1043        action.setActionDefinitionId(ITextEditorActionDefinitionIds.CHANGE_ENCODING);
1044        setAction(ITextEditorActionConstants.CHANGE_ENCODING, action);
1045        markAsPropertyDependentAction(ITextEditorActionConstants.CHANGE_ENCODING, true);
1046
1047        action= new ResourceAction(TextEditorMessages.getBundleForConstructedKeys(), "Editor.ToggleLineNumbersAction.", IAction.AS_CHECK_BOX) { //$NON-NLS-1$
1048
public void run() {
1049                toggleLineNumberRuler();
1050            }
1051        };
1052        action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINENUMBER_TOGGLE);
1053        setAction(ITextEditorActionConstants.LINENUMBERS_TOGGLE, action);
1054
1055        action= new ResourceAction(TextEditorMessages.getBundleForConstructedKeys(), "Editor.ToggleQuickDiffAction.", IAction.AS_CHECK_BOX) { //$NON-NLS-1$
1056
public void run() {
1057                toggleQuickDiffRuler();
1058            }
1059        };
1060        action.setActionDefinitionId(ITextEditorActionDefinitionIds.QUICKDIFF_TOGGLE);
1061        setAction(ITextEditorActionConstants.QUICKDIFF_TOGGLE, action);
1062
1063        action= new RevertLineAction(this, false);
1064        action.setActionDefinitionId(ITextEditorActionDefinitionIds.QUICKDIFF_REVERTLINE);
1065        setAction(ITextEditorActionConstants.QUICKDIFF_REVERTLINE, action);
1066
1067        action= new RevertSelectionAction(this, false);
1068        setAction(ITextEditorActionConstants.QUICKDIFF_REVERTSELECTION, action);
1069
1070        action= new RevertBlockAction(this, false);
1071        setAction(ITextEditorActionConstants.QUICKDIFF_REVERTBLOCK, action);
1072
1073        action= new RestoreAction(this, false);
1074        setAction(ITextEditorActionConstants.QUICKDIFF_REVERTDELETION, action);
1075
1076        IAction action2= new CompositeRevertAction(this, new IAction[] {
1077                                               getAction(ITextEditorActionConstants.QUICKDIFF_REVERTSELECTION),
1078                                               getAction(ITextEditorActionConstants.QUICKDIFF_REVERTBLOCK),
1079                                               getAction(ITextEditorActionConstants.QUICKDIFF_REVERTDELETION),
1080                                               getAction(ITextEditorActionConstants.QUICKDIFF_REVERTLINE)});
1081        action2.setActionDefinitionId(ITextEditorActionDefinitionIds.QUICKDIFF_REVERT);
1082        setAction(ITextEditorActionConstants.QUICKDIFF_REVERT, action2);
1083        
1084        action= new ResourceAction(TextEditorMessages.getBundleForConstructedKeys(), "Editor.HideRevisionInformationAction.") { //$NON-NLS-1$
1085
public void run() {
1086                if (fLineColumn != null)
1087                    fLineColumn.hideRevisionInformation();
1088            }
1089        };
1090        setAction(ITextEditorActionConstants.REVISION_HIDE_INFO, action);
1091
1092        action= new ResourceAction(TextEditorMessages.getBundleForConstructedKeys(), "Editor.CycleRevisionRenderingAction.") { //$NON-NLS-1$
1093
public void run() {
1094                final RenderingMode[] modes= { IRevisionRulerColumnExtension.AGE, IRevisionRulerColumnExtension.AUTHOR, IRevisionRulerColumnExtension.AUTHOR_SHADED_BY_AGE};
1095                IPreferenceStore store= EditorsUI.getPreferenceStore();
1096                String JavaDoc current= store.getString(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE);
1097                for (int i= 0; i < modes.length; i++) {
1098                    String JavaDoc mode= modes[i].name();
1099                    if (mode.equals(current)) {
1100                        int nextIndex= (i + 1) % modes.length;
1101                        RenderingMode nextMode= modes[nextIndex];
1102                        store.setValue(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE, nextMode.name());
1103                    }
1104                }
1105            }
1106        };
1107        action.setActionDefinitionId(ITextEditorActionDefinitionIds.REVISION_RENDERING_CYCLE);
1108        setAction(ITextEditorActionConstants.REVISION_RENDERING_CYCLE, action);
1109        
1110        action= new BooleanPreferenceToggleAction(TextEditorMessages.getBundleForConstructedKeys(), "Editor.ToggleRevisionAuthorAction.", IAction.AS_CHECK_BOX, EditorsUI.getPreferenceStore(), AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_AUTHOR); //$NON-NLS-1$
1111
action.setActionDefinitionId(ITextEditorActionDefinitionIds.REVISION_AUTHOR_TOGGLE);
1112        setAction(ITextEditorActionConstants.REVISION_SHOW_AUTHOR_TOGGLE, action);
1113        
1114        action= new BooleanPreferenceToggleAction(TextEditorMessages.getBundleForConstructedKeys(), "Editor.ToggleRevisionIdAction.", IAction.AS_CHECK_BOX, EditorsUI.getPreferenceStore(), AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_REVISION); //$NON-NLS-1$
1115
action.setActionDefinitionId(ITextEditorActionDefinitionIds.REVISION_ID_TOGGLE);
1116        setAction(ITextEditorActionConstants.REVISION_SHOW_ID_TOGGLE, action);
1117        
1118        final Shell shell;
1119        if (getSourceViewer() != null)
1120            shell= getSourceViewer().getTextWidget().getShell();
1121        else
1122            shell= null;
1123        action= new ResourceAction(TextEditorMessages.getBundleForConstructedKeys(), "Editor.RulerPreferencesAction.") { //$NON-NLS-1$
1124
public void run() {
1125                String JavaDoc[] preferencePages= collectRulerMenuPreferencePages();
1126                if (preferencePages.length > 0 && (shell == null || !shell.isDisposed()))
1127                    PreferencesUtil.createPreferenceDialogOn(shell, preferencePages[0], preferencePages, null).open();
1128            }
1129
1130        };
1131        setAction(ITextEditorActionConstants.RULER_PREFERENCES, action);
1132
1133        action= new ResourceAction(TextEditorMessages.getBundleForConstructedKeys(), "Editor.ContextPreferencesAction.") { //$NON-NLS-1$
1134
public void run() {
1135                String JavaDoc[] preferencePages= collectContextMenuPreferencePages();
1136                if (preferencePages.length > 0 && (shell == null || !shell.isDisposed()))
1137                    PreferencesUtil.createPreferenceDialogOn(shell, preferencePages[0], preferencePages, null).open();
1138            }
1139        };
1140        action.setId(ITextEditorActionConstants.CONTEXT_PREFERENCES);
1141        setAction(ITextEditorActionConstants.CONTEXT_PREFERENCES, action);
1142
1143        IAction showWhitespaceCharactersAction= getAction(ITextEditorActionConstants.SHOW_WHITESPACE_CHARACTERS);
1144        if (showWhitespaceCharactersAction instanceof ShowWhitespaceCharactersAction)
1145            ((ShowWhitespaceCharactersAction)showWhitespaceCharactersAction).setPreferenceStore(EditorsUI.getPreferenceStore());
1146        
1147        setAction(ActionFactory.REFRESH.getId(), new RefreshEditorAction(this));
1148        markAsPropertyDependentAction(ActionFactory.REFRESH.getId(), true);
1149    }
1150
1151    public Object JavaDoc getAdapter(Class JavaDoc adapter) {
1152        if (IGotoMarker.class.equals(adapter))
1153            return fGotoMarkerAdapter;
1154
1155        if (IAnnotationAccess.class.equals(adapter))
1156            return getAnnotationAccess();
1157
1158        if (adapter == IShowInSource.class) {
1159            return new IShowInSource() {
1160                public ShowInContext getShowInContext() {
1161                    ISelection selection= null;
1162                    ISelectionProvider selectionProvider= getSelectionProvider();
1163                    if (selectionProvider != null)
1164                        selection= selectionProvider.getSelection();
1165                    return new ShowInContext(getEditorInput(), selection);
1166                }
1167            };
1168        }
1169
1170        if (IRevisionRulerColumn.class.equals(adapter)) {
1171            if (fLineNumberRulerColumn instanceof IRevisionRulerColumn)
1172                return fLineNumberRulerColumn;
1173        }
1174
1175        return super.getAdapter(adapter);
1176    
1177    }
1178
1179    /*
1180     * If there is no explicit document provider set, the implicit one is
1181     * re-initialized based on the given editor input.
1182     *
1183     * @see org.eclipse.ui.texteditor.AbstractTextEditor#setDocumentProvider(org.eclipse.ui.IEditorInput)
1184     */

1185    protected void setDocumentProvider(IEditorInput input) {
1186        fImplicitDocumentProvider= DocumentProviderRegistry.getDefault().getDocumentProvider(input);
1187        IDocumentProvider provider= super.getDocumentProvider();
1188        if (provider instanceof ForwardingDocumentProvider) {
1189            ForwardingDocumentProvider forwarder= (ForwardingDocumentProvider) provider;
1190            forwarder.setParentProvider(fImplicitDocumentProvider);
1191        }
1192    }
1193
1194    /*
1195     * @see org.eclipse.ui.texteditor.ITextEditor#getDocumentProvider()
1196     */

1197    public IDocumentProvider getDocumentProvider() {
1198        IDocumentProvider provider= super.getDocumentProvider();
1199        if (provider == null)
1200            return fImplicitDocumentProvider;
1201        return provider;
1202    }
1203
1204    /*
1205     * @see org.eclipse.ui.texteditor.AbstractTextEditor#disposeDocumentProvider()
1206     */

1207    protected void disposeDocumentProvider() {
1208        super.disposeDocumentProvider();
1209        fImplicitDocumentProvider= null;
1210    }
1211
1212    /*
1213     * @see AbstractTextEditor#doSetInput(IEditorInput)
1214     *
1215     * This implementation also updates change information in the quick diff
1216     * ruler.
1217     */

1218    protected void doSetInput(IEditorInput input) throws CoreException {
1219        fIsDerivedStateValidated= false;
1220        fIsEditingDerivedFileAllowed= true;
1221        
1222        if (fLineColumn != null)
1223            fLineColumn.hideRevisionInformation();
1224
1225        super.doSetInput(input);
1226        
1227        RulerColumnDescriptor lineNumberColumnDescriptor= RulerColumnRegistry.getDefault().getColumnDescriptor(LineNumberColumn.ID);
1228        if (lineNumberColumnDescriptor != null) {
1229            IColumnSupport columnSupport= (IColumnSupport)getAdapter(IColumnSupport.class);
1230            columnSupport.setColumnVisible(lineNumberColumnDescriptor, isLineNumberRulerVisible() || isPrefQuickDiffAlwaysOn());
1231        }
1232    }
1233    
1234    /**
1235     * This implementation asks the user for the workspace path of a file resource and saves the document there.
1236     *
1237     * @param progressMonitor the progress monitor to be used
1238     * @since 3.2
1239     */

1240    protected void performSaveAs(IProgressMonitor progressMonitor) {
1241        Shell shell= getSite().getShell();
1242        final IEditorInput input= getEditorInput();
1243
1244        IDocumentProvider provider= getDocumentProvider();
1245        final IEditorInput newInput;
1246        
1247        if (input instanceof IURIEditorInput && !(input instanceof IFileEditorInput)) {
1248            FileDialog dialog= new FileDialog(shell, SWT.SAVE);
1249            IPath oldPath= URIUtil.toPath(((IURIEditorInput)input).getURI());
1250            if (oldPath != null) {
1251                dialog.setFileName(oldPath.lastSegment());
1252                dialog.setFilterPath(oldPath.toOSString());
1253            }
1254            
1255            String JavaDoc path= dialog.open();
1256            if (path == null) {
1257                if (progressMonitor != null)
1258                    progressMonitor.setCanceled(true);
1259                return;
1260            }
1261
1262            // Check whether file exists and if so, confirm overwrite
1263
final File JavaDoc localFile= new File JavaDoc(path);
1264            if (localFile.exists()) {
1265                MessageDialog overwriteDialog= new MessageDialog(
1266                        shell,
1267                        TextEditorMessages.AbstractDecoratedTextEditor_saveAs_overwrite_title,
1268                        null,
1269                        NLSUtility.format(TextEditorMessages.AbstractDecoratedTextEditor_saveAs_overwrite_message, path),
1270                        MessageDialog.WARNING,
1271                        new String JavaDoc[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL },
1272                        1); // 'No' is the default
1273
if (overwriteDialog.open() != Window.OK) {
1274                    if (progressMonitor != null) {
1275                        progressMonitor.setCanceled(true);
1276                        return;
1277                    }
1278                }
1279            }
1280
1281            IFileStore fileStore;
1282            try {
1283                fileStore= EFS.getStore(localFile.toURI());
1284            } catch (CoreException ex) {
1285                EditorsPlugin.log(ex.getStatus());
1286                String JavaDoc title= TextEditorMessages.AbstractDecoratedTextEditor_error_saveAs_title;
1287                String JavaDoc msg= NLSUtility.format(TextEditorMessages.AbstractDecoratedTextEditor_error_saveAs_message, ex.getMessage());
1288                MessageDialog.openError(shell, title, msg);
1289                return;
1290            }
1291            
1292            IFile file= getWorkspaceFile(fileStore);
1293            if (file != null)
1294                newInput= new FileEditorInput(file);
1295            else
1296                newInput= new FileStoreEditorInput(fileStore);
1297            
1298        } else {
1299            SaveAsDialog dialog= new SaveAsDialog(shell);
1300
1301            IFile original= (input instanceof IFileEditorInput) ? ((IFileEditorInput) input).getFile() : null;
1302            if (original != null)
1303                dialog.setOriginalFile(original);
1304
1305            dialog.create();
1306
1307            if (provider.isDeleted(input) && original != null) {
1308                String JavaDoc message= NLSUtility.format(TextEditorMessages.AbstractDecoratedTextEditor_warning_saveAs_deleted, original.getName());
1309                dialog.setErrorMessage(null);
1310                dialog.setMessage(message, IMessageProvider.WARNING);
1311            }
1312
1313            if (dialog.open() == Window.CANCEL) {
1314                if (progressMonitor != null)
1315                    progressMonitor.setCanceled(true);
1316                return;
1317            }
1318            
1319            IPath filePath= dialog.getResult();
1320            if (filePath == null) {
1321                if (progressMonitor != null)
1322                    progressMonitor.setCanceled(true);
1323                return;
1324            }
1325            
1326            IWorkspace workspace= ResourcesPlugin.getWorkspace();
1327            IFile file= workspace.getRoot().getFile(filePath);
1328            newInput= new FileEditorInput(file);
1329
1330        }
1331        
1332        if (provider == null) {
1333            // editor has programmatically been closed while the dialog was open
1334
return;
1335        }
1336
1337        boolean success= false;
1338        try {
1339
1340            provider.aboutToChange(newInput);
1341            provider.saveDocument(progressMonitor, newInput, provider.getDocument(input), true);
1342            success= true;
1343
1344        } catch (CoreException x) {
1345            final IStatus status= x.getStatus();
1346            if (status == null || status.getSeverity() != IStatus.CANCEL) {
1347                String JavaDoc title= TextEditorMessages.AbstractDecoratedTextEditor_error_saveAs_title;
1348                String JavaDoc msg= NLSUtility.format(TextEditorMessages.AbstractDecoratedTextEditor_error_saveAs_message, x.getMessage());
1349                MessageDialog.openError(shell, title, msg);
1350            }
1351        } finally {
1352            provider.changed(newInput);
1353            if (success)
1354                setInput(newInput);
1355        }
1356
1357        if (progressMonitor != null)
1358            progressMonitor.setCanceled(!success);
1359    }
1360
1361    /**
1362     * Checks whether there given file store points
1363     * to a file in the workspace. Only returns a
1364     * workspace file if there's a single match.
1365     *
1366     * @param fileStore the file store
1367     * @return the <code>IFile</code> that matches the given file store
1368     * @since 3.2
1369     */

1370    private IFile getWorkspaceFile(IFileStore fileStore) {
1371        IWorkspaceRoot workspaceRoot= ResourcesPlugin.getWorkspace().getRoot();
1372        IFile[] files= workspaceRoot.findFilesForLocation(URIUtil.toPath(fileStore.toURI()));
1373        if (files != null && files.length == 1)
1374            return files[0];
1375        return null;
1376    }
1377
1378    /*
1379     * @see org.eclipse.ui.texteditor.AbstractTextEditor#rulerContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager)
1380     * @since 3.1
1381     */

1382    protected void rulerContextMenuAboutToShow(IMenuManager menu) {
1383        /*
1384         * XXX: workaround for reliable menu item ordering.
1385         * This can be changed once the action contribution story converges,
1386         * see http://dev.eclipse.org/viewcvs/index.cgi/~checkout~/platform-ui-home/R3_1/dynamic_teams/dynamic_teams.html#actionContributions
1387         */

1388        // pre-install menus for contributions and call super
1389
menu.add(new Separator("debug")); //$NON-NLS-1$
1390
menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
1391        menu.add(new GroupMarker(ITextEditorActionConstants.GROUP_RESTORE));
1392        menu.add(new Separator("add")); //$NON-NLS-1$
1393
menu.add(new Separator(ITextEditorActionConstants.GROUP_RULERS));
1394        menu.add(new Separator(ITextEditorActionConstants.GROUP_REST));
1395
1396        super.rulerContextMenuAboutToShow(menu);
1397        
1398        addRulerContributionActions(menu);
1399
1400        /* quick diff */
1401        if (isEditorInputModifiable()) {
1402            IAction quickdiffAction= getAction(ITextEditorActionConstants.QUICKDIFF_TOGGLE);
1403            quickdiffAction.setChecked(isChangeInformationShowing());
1404            menu.appendToGroup(ITextEditorActionConstants.GROUP_RULERS, quickdiffAction);
1405
1406            if (isChangeInformationShowing()) {
1407                TextEditorAction revertLine= new RevertLineAction(this, true);
1408                TextEditorAction revertSelection= new RevertSelectionAction(this, true);
1409                TextEditorAction revertBlock= new RevertBlockAction(this, true);
1410                TextEditorAction revertDeletion= new RestoreAction(this, true);
1411
1412                revertSelection.update();
1413                revertBlock.update();
1414                revertLine.update();
1415                revertDeletion.update();
1416
1417                // only add block action if selection action is not enabled
1418
if (revertSelection.isEnabled())
1419                    menu.appendToGroup(ITextEditorActionConstants.GROUP_RESTORE, revertSelection);
1420                else if (revertBlock.isEnabled())
1421                    menu.appendToGroup(ITextEditorActionConstants.GROUP_RESTORE, revertBlock);
1422                if (revertLine.isEnabled())
1423                    menu.appendToGroup(ITextEditorActionConstants.GROUP_RESTORE, revertLine);
1424                if (revertDeletion.isEnabled())
1425                    menu.appendToGroup(ITextEditorActionConstants.GROUP_RESTORE, revertDeletion);
1426            }
1427        }
1428        
1429        // revision info
1430
if (fLineColumn != null && fLineColumn.isShowingRevisionInformation()) {
1431            IMenuManager revisionMenu= new MenuManager(TextEditorMessages.AbstractDecoratedTextEditor_revisions_menu);
1432            menu.appendToGroup(ITextEditorActionConstants.GROUP_RULERS, revisionMenu);
1433            
1434            IAction hideRevisionInfoAction= getAction(ITextEditorActionConstants.REVISION_HIDE_INFO);
1435            revisionMenu.add(hideRevisionInfoAction);
1436            revisionMenu.add(new Separator());
1437            
1438            String JavaDoc[] labels= { TextEditorMessages.AbstractDecoratedTextEditor_revision_colors_option_by_date, TextEditorMessages.AbstractDecoratedTextEditor_revision_colors_option_by_author, TextEditorMessages.AbstractDecoratedTextEditor_revision_colors_option_by_author_and_date };
1439            final RenderingMode[] modes= { IRevisionRulerColumnExtension.AGE, IRevisionRulerColumnExtension.AUTHOR, IRevisionRulerColumnExtension.AUTHOR_SHADED_BY_AGE};
1440            final IPreferenceStore uiStore= EditorsUI.getPreferenceStore();
1441            String JavaDoc current= uiStore.getString(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE);
1442            for (int i= 0; i < modes.length; i++) {
1443                final String JavaDoc mode= modes[i].name();
1444                IAction action= new Action(labels[i], IAction.AS_RADIO_BUTTON) {
1445                    public void run() {
1446                        // set preference globally, LineNumberColumn reacts on preference change
1447
uiStore.setValue(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE, mode);
1448                    }
1449                };
1450                action.setChecked(mode.equals(current));
1451                revisionMenu.add(action);
1452            }
1453            
1454            revisionMenu.add(new Separator());
1455
1456            revisionMenu.add(getAction(ITextEditorActionConstants.REVISION_SHOW_AUTHOR_TOGGLE));
1457            revisionMenu.add(getAction(ITextEditorActionConstants.REVISION_SHOW_ID_TOGGLE));
1458        }
1459
1460        IAction lineNumberAction= getAction(ITextEditorActionConstants.LINENUMBERS_TOGGLE);
1461        lineNumberAction.setChecked(fLineColumn != null && fLineColumn.isShowingLineNumbers());
1462        menu.appendToGroup(ITextEditorActionConstants.GROUP_RULERS, lineNumberAction);
1463
1464        IAction preferencesAction= getAction(ITextEditorActionConstants.RULER_PREFERENCES);
1465        menu.appendToGroup(ITextEditorActionConstants.GROUP_RULERS, new Separator(ITextEditorActionConstants.GROUP_SETTINGS));
1466        menu.appendToGroup(ITextEditorActionConstants.GROUP_SETTINGS, preferencesAction);
1467    }
1468    
1469    /**
1470     * Adds "show" actions for all contributed rulers that support it.
1471     *
1472     * @param menu the ruler context menu
1473     * @since 3.3
1474     */

1475    private void addRulerContributionActions(IMenuManager menu) {
1476        // store directly in generic editor preferences
1477
final IColumnSupport support= (IColumnSupport) getAdapter(IColumnSupport.class);
1478        IPreferenceStore store= EditorsUI.getPreferenceStore();
1479        final RulerColumnPreferenceAdapter adapter= new RulerColumnPreferenceAdapter(store, AbstractTextEditor.PREFERENCE_RULER_CONTRIBUTIONS);
1480        List JavaDoc descriptors= RulerColumnRegistry.getDefault().getColumnDescriptors();
1481        for (Iterator JavaDoc t= descriptors.iterator(); t.hasNext();) {
1482            final RulerColumnDescriptor descriptor= (RulerColumnDescriptor) t.next();
1483            if (!descriptor.isIncludedInMenu() || !support.isColumnSupported(descriptor))
1484                continue;
1485            final boolean isVisible= support.isColumnVisible(descriptor);
1486            IAction action= new Action(MessageFormat.format(TextEditorMessages.AbstractDecoratedTextEditor_show_ruler_label, new Object JavaDoc[] {descriptor.getName()}), IAction.AS_CHECK_BOX) {
1487                public void run() {
1488                    if (descriptor.isGlobal())
1489                        // column state is modified via preference listener of AbstractTextEditor
1490
adapter.setEnabled(descriptor, !isVisible);
1491                    else
1492                        // directly modify column for this editor instance
1493
support.setColumnVisible(descriptor, !isVisible);
1494                }
1495            };
1496            action.setChecked(isVisible);
1497            action.setImageDescriptor(descriptor.getIcon());
1498            menu.appendToGroup(ITextEditorActionConstants.GROUP_RULERS, action);
1499        }
1500    }
1501    
1502    /**
1503     * Toggles the line number global preference and shows the line number ruler
1504     * accordingly.
1505     *
1506     * @since 3.1
1507     */

1508    private void toggleLineNumberRuler() {
1509        // globally
1510
IPreferenceStore store= EditorsUI.getPreferenceStore();
1511        store.setValue(LINE_NUMBER_RULER, !isLineNumberRulerVisible());
1512    }
1513
1514    /**
1515     * Toggles the quick diff global preference and shows the quick diff ruler
1516     * accordingly.
1517     *
1518     * @since 3.1
1519     */

1520    private void toggleQuickDiffRuler() {
1521        // change the visibility locally if this editor is not in sync with the global preference
1522
// toggle the preference if we are in sync.
1523
IPreferenceStore store= EditorsUI.getPreferenceStore();
1524        boolean current= store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON);
1525        if (current == isChangeInformationShowing())
1526            store.setValue(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON, !current);
1527        else
1528            showChangeInformation(current);
1529    }
1530
1531    /*
1532     * @see org.eclipse.ui.texteditor.AbstractTextEditor#editorContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager)
1533     * @since 3.1
1534     */

1535    protected void editorContextMenuAboutToShow(IMenuManager menu) {
1536        super.editorContextMenuAboutToShow(menu);
1537
1538        IAction preferencesAction= getAction(ITextEditorActionConstants.CONTEXT_PREFERENCES);
1539        menu.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, new Separator(ITextEditorActionConstants.GROUP_SETTINGS));
1540        menu.appendToGroup(ITextEditorActionConstants.GROUP_SETTINGS, preferencesAction);
1541        
1542        menu.appendToGroup(ITextEditorActionConstants.GROUP_SAVE, new Separator(ITextEditorActionConstants.GROUP_OPEN));
1543        MenuManager showInSubMenu= new MenuManager(getShowInMenuLabel());
1544        showInSubMenu.add(ContributionItemFactory.VIEWS_SHOW_IN.create(getEditorSite().getWorkbenchWindow()));
1545        menu.appendToGroup(ITextEditorActionConstants.GROUP_OPEN, showInSubMenu);
1546    }
1547
1548    /**
1549     * Returns the menu label for 'Show In' together with its key binding string.
1550     *
1551     * @return the 'Show In' menu label
1552     * @since 3.2
1553     */

1554    private String JavaDoc getShowInMenuLabel() {
1555        String JavaDoc keyBinding= null;
1556        
1557        IBindingService bindingService= (IBindingService)PlatformUI.getWorkbench().getAdapter(IBindingService.class);
1558        if (bindingService != null)
1559            keyBinding= bindingService.getBestActiveBindingFormattedFor("org.eclipse.ui.navigate.showInQuickMenu"); //$NON-NLS-1$
1560

1561        if (keyBinding == null)
1562            keyBinding= ""; //$NON-NLS-1$
1563

1564        return NLS.bind(TextEditorMessages.AbstractDecoratedTextEditor_showIn_menu, keyBinding);
1565    }
1566
1567    /**
1568     * Returns the preference page ids of the preference pages to be shown
1569     * when executing the preferences action from the editor context menu.
1570     * <p>
1571     * Subclasses may extend or replace.
1572     * </p>
1573     *
1574     * @return the preference page ids to show, may be empty
1575     * @since 3.1
1576     */

1577    protected String JavaDoc[] collectContextMenuPreferencePages() {
1578        return new String JavaDoc[] {
1579            "org.eclipse.ui.preferencePages.GeneralTextEditor", //$NON-NLS-1$
1580
"org.eclipse.ui.editors.preferencePages.Annotations", //$NON-NLS-1$
1581
"org.eclipse.ui.editors.preferencePages.QuickDiff", //$NON-NLS-1$
1582
"org.eclipse.ui.editors.preferencePages.Accessibility", //$NON-NLS-1$
1583
"org.eclipse.ui.editors.preferencePages.Spelling", //$NON-NLS-1$
1584
"org.eclipse.ui.editors.preferencePages.LinkedModePreferencePage", //$NON-NLS-1$
1585
};
1586    }
1587
1588    /**
1589     * Returns the preference page ids of the preference pages to be shown when
1590     * executing the preferences action from the editor ruler context menu.
1591     * <p>
1592     * The default is to return the same list as
1593     * <code>collectContextMenuPreferencePages</code>.
1594     * </p>
1595     * <p>
1596     * Subclasses may extend or replace.
1597     * </p>
1598     *
1599     * @return the preference page ids to show, may be empty
1600     * @since 3.1
1601     */

1602    protected String JavaDoc[] collectRulerMenuPreferencePages() {
1603        return collectContextMenuPreferencePages();
1604    }
1605    
1606    /*
1607     * @see AbstractTextEditor#getUndoRedoOperationApprover(IUndoContext)
1608     * @since 3.1
1609     */

1610    protected IOperationApprover getUndoRedoOperationApprover(IUndoContext undoContext) {
1611        IEditorInput input= getEditorInput();
1612        if (input != null && input.getAdapter(IResource.class) != null)
1613            return new NonLocalUndoUserApprover(undoContext, this, new Object JavaDoc [] { input }, IResource.class);
1614        return super.getUndoRedoOperationApprover(undoContext);
1615    }
1616    
1617    /**
1618     * Returns whether the given annotation is configured as a target for the
1619     * "Go to Next/Previous Annotation" actions.
1620     * <p>
1621     * The annotation is a target if their annotation type is configured to be
1622     * in the Next/Previous tool bar drop down menu and if it is checked.
1623     * </p>
1624     *
1625     * @param annotation the annotation
1626     * @return <code>true</code> if this is a target, <code>false</code> otherwise
1627     * @since 3.2
1628     */

1629    protected boolean isNavigationTarget(Annotation annotation) {
1630        AnnotationPreference preference= getAnnotationPreferenceLookup().getAnnotationPreference(annotation);
1631// See bug 41689
1632
// String key= forward ? preference.getIsGoToNextNavigationTargetKey() : preference.getIsGoToPreviousNavigationTargetKey();
1633
String JavaDoc key= preference == null ? null : preference.getIsGoToNextNavigationTargetKey();
1634        return (key != null && getPreferenceStore().getBoolean(key));
1635    }
1636    
1637    /**
1638     * {@inheritDoc}
1639     * <p>
1640     * This extended implementation updates views that also show the
1641     * select marker annotation.
1642     * </p>
1643     * @since 3.2
1644     */

1645    public Annotation gotoAnnotation(boolean forward) {
1646        Annotation annotation= super.gotoAnnotation(forward);
1647        if (annotation != null)
1648            updateMarkerViews(annotation);
1649        return annotation;
1650    }
1651    
1652    /**
1653     * Updates visible views that show markers.
1654     * <p>
1655     * If the given annotation can be associated with a marker then
1656     * this method tries select the this marker in views that show
1657     * markers.
1658     * </p>
1659     * @param annotation
1660     * @since 3.2
1661     */

1662    protected void updateMarkerViews(Annotation annotation) {
1663        IMarker marker= null;
1664        if (annotation instanceof MarkerAnnotation)
1665            marker= ((MarkerAnnotation)annotation).getMarker();
1666        
1667        if (marker != null) {
1668            try {
1669                fIsUpdatingMarkerViews= true;
1670                IWorkbenchPage page= getSite().getPage();
1671                MarkerViewUtil.showMarker(page, marker, false);
1672            } finally {
1673                fIsUpdatingMarkerViews= false;
1674            }
1675        }
1676    }
1677
1678    /*
1679     * @see org.eclipse.ui.texteditor.AbstractTextEditor#isTabConversionEnabled()
1680     * @since 3.3
1681     */

1682    protected boolean isTabsToSpacesConversionEnabled() {
1683        return getPreferenceStore() != null && getPreferenceStore().getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS);
1684    }
1685}
1686
Popular Tags