KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > texteditor > LineNumberColumn


1 /*******************************************************************************
2  * Copyright (c) 2006, 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.internal.texteditor;
12
13
14 import java.util.HashMap JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.Map JavaDoc;
17
18 import org.eclipse.core.runtime.Assert;
19
20 import org.eclipse.swt.graphics.Font;
21 import org.eclipse.swt.graphics.RGB;
22 import org.eclipse.swt.widgets.Composite;
23 import org.eclipse.swt.widgets.Control;
24
25 import org.eclipse.jface.text.ITextViewer;
26 import org.eclipse.jface.text.revisions.IRevisionRulerColumn;
27 import org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension;
28 import org.eclipse.jface.text.revisions.RevisionInformation;
29 import org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension.RenderingMode;
30 import org.eclipse.jface.text.source.AnnotationModel;
31 import org.eclipse.jface.text.source.CompositeRuler;
32 import org.eclipse.jface.text.source.IAnnotationHover;
33 import org.eclipse.jface.text.source.IAnnotationModel;
34 import org.eclipse.jface.text.source.IAnnotationModelExtension;
35 import org.eclipse.jface.text.source.IChangeRulerColumn;
36 import org.eclipse.jface.text.source.ILineDifferExtension;
37 import org.eclipse.jface.text.source.ILineDifferExtension2;
38 import org.eclipse.jface.text.source.ISharedTextColors;
39 import org.eclipse.jface.text.source.ISourceViewer;
40 import org.eclipse.jface.text.source.IVerticalRulerColumn;
41 import org.eclipse.jface.text.source.IVerticalRulerInfo;
42 import org.eclipse.jface.text.source.IVerticalRulerInfoExtension;
43 import org.eclipse.jface.text.source.IVerticalRulerListener;
44 import org.eclipse.jface.text.source.LineNumberChangeRulerColumn;
45 import org.eclipse.jface.text.source.LineNumberRulerColumn;
46
47 import org.eclipse.ui.editors.text.EditorsUI;
48
49 import org.eclipse.ui.internal.editors.text.EditorsPlugin;
50
51 import org.eclipse.jface.dialogs.MessageDialogWithToggle;
52 import org.eclipse.jface.preference.IPreferenceStore;
53 import org.eclipse.jface.preference.PreferenceConverter;
54 import org.eclipse.jface.util.IPropertyChangeListener;
55 import org.eclipse.jface.util.PropertyChangeEvent;
56 import org.eclipse.jface.viewers.ISelectionProvider;
57 import org.eclipse.jface.window.Window;
58 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
59 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
60 import org.eclipse.ui.texteditor.AbstractTextEditor;
61 import org.eclipse.ui.texteditor.AnnotationPreference;
62 import org.eclipse.ui.texteditor.ITextEditor;
63 import org.eclipse.ui.texteditor.ITextEditorExtension;
64 import org.eclipse.ui.texteditor.ITextEditorExtension2;
65 import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
66 import org.eclipse.ui.texteditor.quickdiff.QuickDiff;
67 import org.eclipse.ui.texteditor.rulers.AbstractContributedRulerColumn;
68
69 /**
70  * The line number ruler contribution. Encapsulates a {@link LineNumberChangeRulerColumn} as a
71  * contribution to the <code>rulerColumns</code> extension point. Instead of instantiating the
72  * delegate itself, it calls <code>createLineNumberRulerColumn()</code> in
73  * {@link AbstractDecoratedTextEditor} via {@link ICompatibilityForwarder} to maintain compatibility
74  * with previous releases.
75  *
76  * @since 3.3
77  */

78 public class LineNumberColumn extends AbstractContributedRulerColumn implements IVerticalRulerInfo, IVerticalRulerInfoExtension {
79     /**
80      * Forwarder for preference checks and ruler creation. Needed to maintain the forwarded APIs in
81      * {@link AbstractDecoratedTextEditor}.
82      */

83     public static interface ICompatibilityForwarder {
84         IVerticalRulerColumn createLineNumberRulerColumn();
85         boolean isQuickDiffEnabled();
86         boolean isLineNumberRulerVisible();
87     }
88     
89     /** The contribution id of the line number / change ruler. */
90     public static final String JavaDoc ID= "org.eclipse.ui.editors.columns.linenumbers"; //$NON-NLS-1$
91

92     private static final String JavaDoc FG_COLOR_KEY= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR;
93     private static final String JavaDoc BG_COLOR_KEY= AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND;
94     private static final String JavaDoc USE_DEFAULT_BG_KEY= AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT;
95     private final static String JavaDoc LINE_NUMBER_KEY= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER;
96     private final static String JavaDoc REVISION_ASK_BEFORE_QUICKDIFF_SWITCH_KEY= AbstractDecoratedTextEditorPreferenceConstants.REVISION_ASK_BEFORE_QUICKDIFF_SWITCH;
97
98     /**
99      * The delegate and implemenation of the ruler.
100      */

101     private IVerticalRulerColumn fDelegate;
102     /**
103      * The annotation preferences.
104      */

105     private final MarkerAnnotationPreferences fAnnotationPreferences= EditorsPlugin.getDefault().getMarkerAnnotationPreferences();
106
107     /**
108      * Preference dispatcher that registers a single listener so we don't have to manage every
109      * single preference listener.
110      */

111     private PropertyEventDispatcher fDispatcher;
112     private ISourceViewer fViewer;
113     private ICompatibilityForwarder fForwarder;
114
115     /*
116      * @see org.eclipse.jface.text.source.IVerticalRulerColumn#createControl(org.eclipse.jface.text.source.CompositeRuler, org.eclipse.swt.widgets.Composite)
117      */

118     public Control createControl(CompositeRuler parentRuler, Composite parentControl) {
119         Assert.isTrue(fDelegate != null);
120         ITextViewer viewer= parentRuler.getTextViewer();
121         Assert.isLegal(viewer instanceof ISourceViewer);
122         fViewer= (ISourceViewer) viewer;
123         initialize();
124         Control control= fDelegate.createControl(parentRuler, parentControl);
125         return control;
126     }
127
128     /*
129      * @see org.eclipse.jface.text.source.IVerticalRulerColumn#getControl()
130      */

131     public Control getControl() {
132         return fDelegate.getControl();
133     }
134
135     /*
136      * @see org.eclipse.jface.text.source.IVerticalRulerColumn#getWidth()
137      */

138     public int getWidth() {
139         return fDelegate.getWidth();
140     }
141
142     /*
143      * @see org.eclipse.jface.text.source.IVerticalRulerColumn#redraw()
144      */

145     public void redraw() {
146         fDelegate.redraw();
147     }
148
149     /*
150      * @see org.eclipse.jface.text.source.IVerticalRulerColumn#setFont(org.eclipse.swt.graphics.Font)
151      */

152     public void setFont(Font font) {
153         fDelegate.setFont(font);
154     }
155
156     /*
157      * @see org.eclipse.jface.text.source.IVerticalRulerColumn#setModel(org.eclipse.jface.text.source.IAnnotationModel)
158      */

159     public void setModel(IAnnotationModel model) {
160         if (getQuickDiffPreference())
161             fDelegate.setModel(model);
162     }
163     
164     /*
165      * @see org.eclipse.jface.text.source.IVerticalRulerInfo#getLineOfLastMouseButtonActivity()
166      */

167     public int getLineOfLastMouseButtonActivity() {
168         if (fDelegate instanceof IVerticalRulerInfo)
169             ((IVerticalRulerInfo) fDelegate).getLineOfLastMouseButtonActivity();
170         return -1;
171     }
172
173     /*
174      * @see org.eclipse.jface.text.source.IVerticalRulerInfo#toDocumentLineNumber(int)
175      */

176     public int toDocumentLineNumber(int y_coordinate) {
177         if (fDelegate instanceof IVerticalRulerInfo)
178             ((IVerticalRulerInfo) fDelegate).toDocumentLineNumber(y_coordinate);
179         return -1;
180     }
181
182     /*
183      * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#addVerticalRulerListener(org.eclipse.jface.text.source.IVerticalRulerListener)
184      */

185     public void addVerticalRulerListener(IVerticalRulerListener listener) {
186         if (fDelegate instanceof IVerticalRulerInfoExtension)
187             ((IVerticalRulerInfoExtension) fDelegate).addVerticalRulerListener(listener);
188     }
189
190     /*
191      * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#getHover()
192      */

193     public IAnnotationHover getHover() {
194         if (fDelegate instanceof IVerticalRulerInfoExtension)
195             return ((IVerticalRulerInfoExtension) fDelegate).getHover();
196         return null;
197     }
198
199     /*
200      * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#getModel()
201      */

202     public IAnnotationModel getModel() {
203         if (fDelegate instanceof IVerticalRulerInfoExtension)
204             return ((IVerticalRulerInfoExtension) fDelegate).getModel();
205         return null;
206     }
207
208     /*
209      * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#removeVerticalRulerListener(org.eclipse.jface.text.source.IVerticalRulerListener)
210      */

211     public void removeVerticalRulerListener(IVerticalRulerListener listener) {
212         if (fDelegate instanceof IVerticalRulerInfoExtension)
213             ((IVerticalRulerInfoExtension) fDelegate).removeVerticalRulerListener(listener);
214     }
215
216     /*
217      * @see org.eclipse.ui.texteditor.rulers.AbstractContributedRulerColumn#columnRemoved()
218      */

219     public void columnRemoved() {
220         if (fDispatcher != null) {
221             fDispatcher.dispose();
222             fDispatcher= null;
223         }
224     }
225
226     private IPreferenceStore getPreferenceStore() {
227         return EditorsUI.getPreferenceStore();
228     }
229
230     private ISharedTextColors getSharedColors() {
231         return EditorsUI.getSharedTextColors();
232     }
233
234     /**
235      * Initializes the given line number ruler column from the preference store.
236      */

237     private void initialize() {
238         final IPreferenceStore store= getPreferenceStore();
239         if (store == null)
240             return;
241
242         // initial set up
243
updateForegroundColor(store, fDelegate);
244         updateBackgroundColor(store, fDelegate);
245         
246         updateLineNumbersVisibility(fDelegate);
247         updateQuickDiffVisibility(fDelegate);
248         updateCharacterMode(store, fDelegate);
249         updateRevisionRenderingMode(store, fDelegate);
250         updateRevisionAuthorVisibility(store, fDelegate);
251         updateRevisionIdVisibility(store, fDelegate);
252
253         Map JavaDoc annotationPrefs= getAnnotationPreferenceMap();
254         final AnnotationPreference changedPref= (AnnotationPreference) annotationPrefs.get("org.eclipse.ui.workbench.texteditor.quickdiffChange"); //$NON-NLS-1$
255
final AnnotationPreference addedPref= (AnnotationPreference) annotationPrefs.get("org.eclipse.ui.workbench.texteditor.quickdiffAddition"); //$NON-NLS-1$
256
final AnnotationPreference deletedPref= (AnnotationPreference) annotationPrefs.get("org.eclipse.ui.workbench.texteditor.quickdiffDeletion"); //$NON-NLS-1$
257
updateChangedColor(changedPref, store, fDelegate);
258         updateAddedColor(addedPref, store, fDelegate);
259         updateDeletedColor(deletedPref, store, fDelegate);
260
261         fDelegate.redraw();
262
263         // listen to changes
264
fDispatcher= new PropertyEventDispatcher(store);
265
266         fDispatcher.addPropertyChangeListener(FG_COLOR_KEY, new IPropertyChangeListener() {
267             public void propertyChange(PropertyChangeEvent event) {
268                 updateForegroundColor(store, fDelegate);
269                 fDelegate.redraw();
270             }
271         });
272         IPropertyChangeListener backgroundHandler= new IPropertyChangeListener() {
273             public void propertyChange(PropertyChangeEvent event) {
274                 updateBackgroundColor(store, fDelegate);
275                 fDelegate.redraw();
276             }
277         };
278         fDispatcher.addPropertyChangeListener(BG_COLOR_KEY, backgroundHandler);
279         fDispatcher.addPropertyChangeListener(USE_DEFAULT_BG_KEY, backgroundHandler);
280
281         fDispatcher.addPropertyChangeListener(LINE_NUMBER_KEY, new IPropertyChangeListener() {
282             public void propertyChange(PropertyChangeEvent event) {
283                 // only handle quick diff on/off information, but not ruler visibility (handled by AbstractDecoratedTextEditor)
284
updateLineNumbersVisibility(fDelegate);
285             }
286         });
287
288         fDispatcher.addPropertyChangeListener(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_CHARACTER_MODE, new IPropertyChangeListener() {
289             public void propertyChange(PropertyChangeEvent event) {
290                 updateCharacterMode(store, fDelegate);
291             }
292         });
293
294         fDispatcher.addPropertyChangeListener(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE, new IPropertyChangeListener() {
295             public void propertyChange(PropertyChangeEvent event) {
296                 updateRevisionRenderingMode(store, fDelegate);
297             }
298         });
299         
300         fDispatcher.addPropertyChangeListener(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_AUTHOR, new IPropertyChangeListener() {
301             public void propertyChange(PropertyChangeEvent event) {
302                 updateRevisionAuthorVisibility(store, fDelegate);
303             }
304         });
305         
306         fDispatcher.addPropertyChangeListener(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_REVISION, new IPropertyChangeListener() {
307             public void propertyChange(PropertyChangeEvent event) {
308                 updateRevisionIdVisibility(store, fDelegate);
309             }
310         });
311         
312         fDispatcher.addPropertyChangeListener(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON, new IPropertyChangeListener() {
313             public void propertyChange(PropertyChangeEvent event) {
314                 updateQuickDiffVisibility(fDelegate);
315             }
316         });
317
318         if (changedPref != null) {
319             fDispatcher.addPropertyChangeListener(changedPref.getColorPreferenceKey(), new IPropertyChangeListener() {
320                 public void propertyChange(PropertyChangeEvent event) {
321                     updateChangedColor(changedPref, store, fDelegate);
322                     fDelegate.redraw();
323                 }
324             });
325         }
326         if (addedPref != null) {
327             fDispatcher.addPropertyChangeListener(addedPref.getColorPreferenceKey(), new IPropertyChangeListener() {
328                 public void propertyChange(PropertyChangeEvent event) {
329                     updateAddedColor(addedPref, store, fDelegate);
330                     fDelegate.redraw();
331                 }
332             });
333         }
334         if (deletedPref != null) {
335             fDispatcher.addPropertyChangeListener(deletedPref.getColorPreferenceKey(), new IPropertyChangeListener() {
336                 public void propertyChange(PropertyChangeEvent event) {
337                     updateDeletedColor(deletedPref, store, fDelegate);
338                     fDelegate.redraw();
339                 }
340             });
341         }
342     }
343
344     private Map JavaDoc getAnnotationPreferenceMap() {
345         Map JavaDoc annotationPrefs= new HashMap JavaDoc();
346         Iterator JavaDoc iter= fAnnotationPreferences.getAnnotationPreferences().iterator();
347         while (iter.hasNext()) {
348             AnnotationPreference pref= (AnnotationPreference) iter.next();
349             Object JavaDoc type= pref.getAnnotationType();
350             annotationPrefs.put(type, pref);
351         }
352         return annotationPrefs;
353     }
354     
355     private void updateForegroundColor(IPreferenceStore store, IVerticalRulerColumn column) {
356         RGB rgb= getColorFromStore(store, FG_COLOR_KEY);
357         if (rgb == null)
358             rgb= new RGB(0, 0, 0);
359         ISharedTextColors sharedColors= getSharedColors();
360         if (column instanceof LineNumberRulerColumn)
361             ((LineNumberRulerColumn) column).setForeground(sharedColors.getColor(rgb));
362     }
363     
364     private void updateBackgroundColor(IPreferenceStore store, IVerticalRulerColumn column) {
365         // background color: same as editor, or system default
366
RGB rgb;
367         if (store.getBoolean(USE_DEFAULT_BG_KEY))
368             rgb= null;
369         else
370             rgb= getColorFromStore(store, BG_COLOR_KEY);
371         ISharedTextColors sharedColors= getSharedColors();
372         if (column instanceof LineNumberRulerColumn)
373             ((LineNumberRulerColumn) column).setBackground(sharedColors.getColor(rgb));
374     }
375
376     private void updateChangedColor(AnnotationPreference pref, IPreferenceStore store, IVerticalRulerColumn column) {
377         if (pref != null && column instanceof IChangeRulerColumn) {
378             RGB rgb= getColorFromAnnotationPreference(store, pref);
379             ((IChangeRulerColumn) column).setChangedColor(getSharedColors().getColor(rgb));
380         }
381     }
382
383     private void updateAddedColor(AnnotationPreference pref, IPreferenceStore store, IVerticalRulerColumn column) {
384         if (pref != null && column instanceof IChangeRulerColumn) {
385             RGB rgb= getColorFromAnnotationPreference(store, pref);
386             ((IChangeRulerColumn) column).setAddedColor(getSharedColors().getColor(rgb));
387         }
388     }
389     
390     private void updateDeletedColor(AnnotationPreference pref, IPreferenceStore store, IVerticalRulerColumn column) {
391         if (pref != null && column instanceof IChangeRulerColumn) {
392             RGB rgb= getColorFromAnnotationPreference(store, pref);
393             ((IChangeRulerColumn) column).setDeletedColor(getSharedColors().getColor(rgb));
394         }
395     }
396     
397     private void updateCharacterMode(IPreferenceStore store, IVerticalRulerColumn column) {
398         if (column instanceof LineNumberChangeRulerColumn) {
399             LineNumberChangeRulerColumn lncrc= (LineNumberChangeRulerColumn) column;
400             lncrc.setDisplayMode(store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_CHARACTER_MODE));
401         }
402     }
403
404     private void updateLineNumbersVisibility(IVerticalRulerColumn column) {
405         if (column instanceof LineNumberChangeRulerColumn)
406             ((LineNumberChangeRulerColumn) column).showLineNumbers(getLineNumberPreference());
407     }
408     
409     private void updateRevisionRenderingMode(IPreferenceStore store, IVerticalRulerColumn column) {
410         if (column instanceof IRevisionRulerColumnExtension) {
411             String JavaDoc option= store.getString(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE);
412             RenderingMode[] modes= { IRevisionRulerColumnExtension.AUTHOR, IRevisionRulerColumnExtension.AGE, IRevisionRulerColumnExtension.AUTHOR_SHADED_BY_AGE };
413             for (int i= 0; i < modes.length; i++) {
414                 if (modes[i].name().equals(option)) {
415                     ((IRevisionRulerColumnExtension) column).setRevisionRenderingMode(modes[i]);
416                     return;
417                 }
418             }
419         }
420     }
421     
422     private void updateRevisionAuthorVisibility(IPreferenceStore store, IVerticalRulerColumn column) {
423         if (column instanceof IRevisionRulerColumnExtension) {
424             boolean show= store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_AUTHOR);
425             ((IRevisionRulerColumnExtension) column).showRevisionAuthor(show);
426         }
427     }
428     
429     private void updateRevisionIdVisibility(IPreferenceStore store, IVerticalRulerColumn column) {
430         if (column instanceof IRevisionRulerColumnExtension) {
431             boolean show= store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_REVISION);
432             ((IRevisionRulerColumnExtension) column).showRevisionId(show);
433         }
434     }
435     
436     private void updateQuickDiffVisibility(IVerticalRulerColumn column) {
437         boolean show= getQuickDiffPreference();
438         if (show == isShowingChangeInformation())
439             return;
440         
441         if (show)
442             installChangeRulerModel(column);
443         else
444             uninstallChangeRulerModel(column);
445     }
446     
447     /**
448      * Returns whether the line number ruler column should be
449      * visible according to the preference store settings. Subclasses may override this
450      * method to provide a custom preference setting.
451      *
452      * @return <code>true</code> if the line numbers should be visible
453      */

454     private boolean getLineNumberPreference() {
455         if (fForwarder != null)
456             return fForwarder.isLineNumberRulerVisible();
457         IPreferenceStore store= getPreferenceStore();
458         return store != null ? store.getBoolean(LINE_NUMBER_KEY) : false;
459     }
460     
461     /**
462      * Returns whether quick diff info should be visible upon opening an editor
463      * according to the preference store settings.
464      *
465      * @return <code>true</code> if the line numbers should be visible
466      */

467     private boolean getQuickDiffPreference() {
468         if (fForwarder != null)
469             return fForwarder.isQuickDiffEnabled();
470         IPreferenceStore store= getPreferenceStore();
471         boolean setting= store != null ? store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON) : false;
472         if (!setting)
473             return false;
474         
475         boolean modifiable;
476         ITextEditor editor= getEditor();
477         if (editor instanceof ITextEditorExtension2) {
478             ITextEditorExtension2 ext= (ITextEditorExtension2) editor;
479             modifiable= ext.isEditorInputModifiable();
480         } else if (editor instanceof ITextEditorExtension) {
481             ITextEditorExtension ext= (ITextEditorExtension) editor;
482             modifiable= ext.isEditorInputReadOnly();
483         } else if (editor != null) {
484             modifiable= editor.isEditable();
485         } else {
486             modifiable= true;
487         }
488         return modifiable;
489     }
490
491     /**
492      * Extracts the color preference for the given preference from the given store.
493      * If the given store indicates that the default value is to be used, or
494      * the value stored in the preferences store is <code>null</code>,
495      * the value is taken from the <code>AnnotationPreference</code>'s default
496      * color value.
497      * <p>
498      * The return value is
499      * </p>
500      *
501      * @param store the preference store
502      * @param pref the annotation preference
503      * @return the RGB color preference, not <code>null</code>
504      */

505     private static RGB getColorFromAnnotationPreference(IPreferenceStore store, AnnotationPreference pref) {
506         String JavaDoc key= pref.getColorPreferenceKey();
507         RGB rgb= null;
508         if (store.contains(key)) {
509             if (store.isDefault(key))
510                 rgb= pref.getColorPreferenceValue();
511             else
512                 rgb= PreferenceConverter.getColor(store, key);
513         }
514         if (rgb == null)
515             rgb= pref.getColorPreferenceValue();
516         return rgb;
517     }
518     
519     private static RGB getColorFromStore(IPreferenceStore store, String JavaDoc key) {
520         RGB rgb= null;
521         if (store.contains(key)) {
522             if (store.isDefault(key))
523                 rgb= PreferenceConverter.getDefaultColor(store, key);
524             else
525                 rgb= PreferenceConverter.getColor(store, key);
526         }
527         return rgb;
528     }
529     
530     /**
531      * Ensures that quick diff information is displayed and the quick diff provider is the one with
532      * the specified id. If a different quick diff provider is in use, the user may be asked whether
533      * he wants to switch.
534      *
535      * @param diffProviderId the quick diff provider id to use
536      * @return <code>true</code> if quick diff could be enabled for the given id,
537      * <code>false</code> otherwise
538      */

539     private boolean ensureQuickDiffProvider(String JavaDoc diffProviderId) {
540         if (!isShowingChangeInformation())
541             installChangeRulerModel(fDelegate); // FIXME pass provider id
542

543         IAnnotationModel annotationModel= fViewer.getAnnotationModel();
544         IAnnotationModel oldDiffer= getDiffer();
545         if (oldDiffer == null && annotationModel != null)
546             return false; // quick diff is enabled, but no differ? not working for whatever reason
547

548         if (annotationModel == null)
549             annotationModel= new AnnotationModel();
550         if (!(annotationModel instanceof IAnnotationModelExtension))
551             return false;
552
553         QuickDiff util= new QuickDiff();
554         Object JavaDoc oldDifferId= util.getConfiguredQuickDiffProvider(oldDiffer);
555         if (oldDifferId.equals(diffProviderId)) {
556             if (oldDiffer instanceof ILineDifferExtension)
557                 ((ILineDifferExtension) oldDiffer).resume();
558             return true;
559         }
560
561         // Check whether the desired provider is available at all
562
IAnnotationModel newDiffer= util.createQuickDiffAnnotationModel(getEditor(), diffProviderId);
563         if (util.getConfiguredQuickDiffProvider(newDiffer).equals(oldDifferId)) {
564             if (oldDiffer instanceof ILineDifferExtension)
565                 ((ILineDifferExtension) oldDiffer).resume();
566                 return true;
567         }
568         
569         // quick diff is showing with the wrong provider - ask the user whether he wants to switch
570
IPreferenceStore store= EditorsUI.getPreferenceStore();
571         if (oldDiffer != null && !store.getString(REVISION_ASK_BEFORE_QUICKDIFF_SWITCH_KEY).equals(MessageDialogWithToggle.ALWAYS)) {
572             MessageDialogWithToggle toggleDialog= MessageDialogWithToggle.openOkCancelConfirm(
573                     fViewer.getTextWidget().getShell(),
574                     RulerMessages.AbstractDecoratedTextEditor_revision_quickdiff_switch_title,
575                     RulerMessages.AbstractDecoratedTextEditor_revision_quickdiff_switch_message,
576                     RulerMessages.AbstractDecoratedTextEditor_revision_quickdiff_switch_rememberquestion,
577                     true,
578                     store,
579                     REVISION_ASK_BEFORE_QUICKDIFF_SWITCH_KEY);
580             if (toggleDialog.getReturnCode() != Window.OK)
581                 return false;
582         }
583         
584         IAnnotationModelExtension modelExtension=(IAnnotationModelExtension) annotationModel;
585         modelExtension.removeAnnotationModel(IChangeRulerColumn.QUICK_DIFF_MODEL_ID);
586         
587
588         modelExtension.addAnnotationModel(IChangeRulerColumn.QUICK_DIFF_MODEL_ID, newDiffer);
589         
590         if (fDelegate instanceof IChangeRulerColumn)
591             ((IChangeRulerColumn) fDelegate).setModel(annotationModel); // picks up the new model attachment
592

593         return true;
594     }
595
596     /**
597      * Installs the differ annotation model with the current quick diff display.
598      *
599      * @param column the column to install the model on
600      */

601     private void installChangeRulerModel(IVerticalRulerColumn column) {
602         if (column instanceof IChangeRulerColumn) {
603             IAnnotationModel model= getAnnotationModelWithDiffer();
604             ((IChangeRulerColumn) column).setModel(model);
605             if (model != null) {
606                 ISourceViewer viewer= fViewer;
607                 if (viewer != null && viewer.getAnnotationModel() == null)
608                     viewer.showAnnotations(true);
609                 }
610         }
611     }
612
613     /**
614      * Uninstalls the differ annotation model from the current quick diff display.
615      *
616      * @param column the column to remove the model from
617      */

618     private void uninstallChangeRulerModel(IVerticalRulerColumn column) {
619         if (column instanceof IChangeRulerColumn)
620             ((IChangeRulerColumn) column).setModel(null);
621         IAnnotationModel model= getDiffer();
622         if (model instanceof ILineDifferExtension)
623             ((ILineDifferExtension) model).suspend();
624
625         ISourceViewer viewer= fViewer;
626         if (viewer != null && viewer.getAnnotationModel() == null)
627             viewer.showAnnotations(false);
628     }
629
630     /**
631      * Returns the annotation model that contains the quick diff annotation model.
632      * <p>
633      * Extracts the line differ from the displayed document's annotation model. If none can be found,
634      * a new differ is created and attached to the annotation model.</p>
635      *
636      * @return the annotation model that contains the line differ, or <code>null</code> if none could be found or created
637      * @see IChangeRulerColumn#QUICK_DIFF_MODEL_ID
638      */

639     private IAnnotationModel getAnnotationModelWithDiffer() {
640         ISourceViewer viewer= fViewer;
641         if (viewer == null)
642             return null;
643         
644         IAnnotationModel m= viewer.getAnnotationModel();
645         IAnnotationModelExtension model= null;
646         if (m instanceof IAnnotationModelExtension)
647             model= (IAnnotationModelExtension) m;
648         
649         IAnnotationModel differ= getDiffer();
650         // create diff model if it doesn't
651
if (differ == null) {
652             IPreferenceStore store= getPreferenceStore();
653             if (store != null) {
654                 String JavaDoc defaultId= store.getString(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_DEFAULT_PROVIDER);
655                 differ= new QuickDiff().createQuickDiffAnnotationModel(getEditor(), defaultId);
656                 if (differ != null) {
657                     if (model == null)
658                         model= new AnnotationModel();
659                     model.addAnnotationModel(IChangeRulerColumn.QUICK_DIFF_MODEL_ID, differ);
660                 }
661             }
662         } else if (differ instanceof ILineDifferExtension2) {
663             if (((ILineDifferExtension2) differ).isSuspended())
664                 ((ILineDifferExtension) differ).resume();
665         } else if (differ instanceof ILineDifferExtension) {
666             ((ILineDifferExtension) differ).resume();
667         }
668         
669         return (IAnnotationModel)model;
670     }
671
672     /**
673      * Extracts the line differ from the displayed document's annotation model. If none can be found,
674      * <code>null</code> is returned.
675      *
676      * @return the line differ, or <code>null</code> if none could be found
677      */

678     private IAnnotationModel getDiffer() {
679         // get annotation model extension
680
ISourceViewer viewer= fViewer;
681         if (viewer == null)
682             return null;
683
684         IAnnotationModel m= viewer.getAnnotationModel();
685         if (m == null && fDelegate instanceof IChangeRulerColumn)
686             m= ((IChangeRulerColumn)fDelegate).getModel();
687         
688         if (!(m instanceof IAnnotationModelExtension))
689             return null;
690         
691         IAnnotationModelExtension model= (IAnnotationModelExtension)m;
692
693         // get diff model if it exists already
694
return model.getAnnotationModel(IChangeRulerColumn.QUICK_DIFF_MODEL_ID);
695     }
696
697     /**
698      * Sets the forwarder. Used by {@link AbstractDecoratedTextEditor} to maintain the contract of
699      * its {@link AbstractDecoratedTextEditor#createLineNumberRulerColumn} method.
700      *
701      * @param forwarder the forwarder
702      */

703     public void setForwarder(ICompatibilityForwarder forwarder) {
704         fForwarder= forwarder;
705         fDelegate= forwarder.createLineNumberRulerColumn();
706     }
707
708     /**
709      * Initializes the given line number ruler column from the preference store.
710      *
711      * @param rulerColumn the ruler column to be initialized
712      */

713     public void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) {
714         IPreferenceStore store= getPreferenceStore();
715         if (store != null) {
716             updateForegroundColor(store, rulerColumn);
717             updateBackgroundColor(store, rulerColumn);
718             updateLineNumbersVisibility(rulerColumn);
719             rulerColumn.redraw();
720         }
721     }
722
723     /**
724      * Returns <code>true</code> if the ruler is showing line numbers, <code>false</code> if it
725      * is only showing change information.
726      *
727      * @return <code>true</code> if line numbers are shown, <code>false</code> otherwise
728      */

729     public boolean isShowingLineNumbers() {
730         return fDelegate instanceof LineNumberChangeRulerColumn && ((LineNumberChangeRulerColumn) fDelegate).isShowingLineNumbers();
731     }
732     
733     /**
734      * Returns <code>true</code> if the ruler is showing change information, <code>false</code>
735      * if it is only showing line numbers.
736      *
737      * @return <code>true</code> if change information is shown, <code>false</code> otherwise
738      */

739     public boolean isShowingChangeInformation() {
740         return fDelegate instanceof LineNumberChangeRulerColumn && ((LineNumberChangeRulerColumn) fDelegate).isShowingChangeInformation();
741     }
742
743     /**
744      * Shows revision information on the receiver.
745      *
746      * @param info the revision information to show
747      * @param quickDiffProviderId the id of the corresponding quick diff provider
748      */

749     public void showRevisionInformation(RevisionInformation info, String JavaDoc quickDiffProviderId) {
750         if (!ensureQuickDiffProvider(quickDiffProviderId))
751             return;
752
753         if (fDelegate instanceof IRevisionRulerColumn)
754             ((IRevisionRulerColumn) fDelegate).setRevisionInformation(info);
755     }
756
757     /**
758      * Hides revision information.
759      */

760     public void hideRevisionInformation() {
761         if (fDelegate instanceof IRevisionRulerColumn)
762             ((IRevisionRulerColumn) fDelegate).setRevisionInformation(null);
763     }
764     
765     /**
766      * Returns <code>true</code> if the ruler is showing revision information, <code>false</code>
767      * if it is only showing line numbers.
768      *
769      * @return <code>true</code> if revision information is shown, <code>false</code> otherwise
770      */

771     public boolean isShowingRevisionInformation() {
772         if (fDelegate instanceof LineNumberChangeRulerColumn)
773             return ((LineNumberChangeRulerColumn) fDelegate).isShowingRevisionInformation();
774         return false;
775     }
776
777     /**
778      * Returns the selection provider of the revision column, <code>null</code> if none is
779      * available.
780      *
781      * @return the revision selection provider
782      */

783     public ISelectionProvider getRevisionSelectionProvider() {
784         if (fDelegate instanceof IRevisionRulerColumnExtension)
785             return ((IRevisionRulerColumnExtension) fDelegate).getRevisionSelectionProvider();
786         return null;
787     }
788 }
789
Popular Tags