001: /*******************************************************************************
002: * Copyright (c) 2006, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.texteditor;
011:
012: import java.util.HashMap;
013: import java.util.Iterator;
014: import java.util.Map;
015:
016: import org.eclipse.core.runtime.Assert;
017:
018: import org.eclipse.swt.graphics.Font;
019: import org.eclipse.swt.graphics.RGB;
020: import org.eclipse.swt.widgets.Composite;
021: import org.eclipse.swt.widgets.Control;
022:
023: import org.eclipse.jface.text.ITextViewer;
024: import org.eclipse.jface.text.revisions.IRevisionRulerColumn;
025: import org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension;
026: import org.eclipse.jface.text.revisions.RevisionInformation;
027: import org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension.RenderingMode;
028: import org.eclipse.jface.text.source.AnnotationModel;
029: import org.eclipse.jface.text.source.CompositeRuler;
030: import org.eclipse.jface.text.source.IAnnotationHover;
031: import org.eclipse.jface.text.source.IAnnotationModel;
032: import org.eclipse.jface.text.source.IAnnotationModelExtension;
033: import org.eclipse.jface.text.source.IChangeRulerColumn;
034: import org.eclipse.jface.text.source.ILineDifferExtension;
035: import org.eclipse.jface.text.source.ILineDifferExtension2;
036: import org.eclipse.jface.text.source.ISharedTextColors;
037: import org.eclipse.jface.text.source.ISourceViewer;
038: import org.eclipse.jface.text.source.IVerticalRulerColumn;
039: import org.eclipse.jface.text.source.IVerticalRulerInfo;
040: import org.eclipse.jface.text.source.IVerticalRulerInfoExtension;
041: import org.eclipse.jface.text.source.IVerticalRulerListener;
042: import org.eclipse.jface.text.source.LineNumberChangeRulerColumn;
043: import org.eclipse.jface.text.source.LineNumberRulerColumn;
044:
045: import org.eclipse.ui.editors.text.EditorsUI;
046:
047: import org.eclipse.ui.internal.editors.text.EditorsPlugin;
048:
049: import org.eclipse.jface.dialogs.MessageDialogWithToggle;
050: import org.eclipse.jface.preference.IPreferenceStore;
051: import org.eclipse.jface.preference.PreferenceConverter;
052: import org.eclipse.jface.util.IPropertyChangeListener;
053: import org.eclipse.jface.util.PropertyChangeEvent;
054: import org.eclipse.jface.viewers.ISelectionProvider;
055: import org.eclipse.jface.window.Window;
056: import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
057: import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
058: import org.eclipse.ui.texteditor.AbstractTextEditor;
059: import org.eclipse.ui.texteditor.AnnotationPreference;
060: import org.eclipse.ui.texteditor.ITextEditor;
061: import org.eclipse.ui.texteditor.ITextEditorExtension;
062: import org.eclipse.ui.texteditor.ITextEditorExtension2;
063: import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
064: import org.eclipse.ui.texteditor.quickdiff.QuickDiff;
065: import org.eclipse.ui.texteditor.rulers.AbstractContributedRulerColumn;
066:
067: /**
068: * The line number ruler contribution. Encapsulates a {@link LineNumberChangeRulerColumn} as a
069: * contribution to the <code>rulerColumns</code> extension point. Instead of instantiating the
070: * delegate itself, it calls <code>createLineNumberRulerColumn()</code> in
071: * {@link AbstractDecoratedTextEditor} via {@link ICompatibilityForwarder} to maintain compatibility
072: * with previous releases.
073: *
074: * @since 3.3
075: */
076: public class LineNumberColumn extends AbstractContributedRulerColumn
077: implements IVerticalRulerInfo, IVerticalRulerInfoExtension {
078: /**
079: * Forwarder for preference checks and ruler creation. Needed to maintain the forwarded APIs in
080: * {@link AbstractDecoratedTextEditor}.
081: */
082: public static interface ICompatibilityForwarder {
083: IVerticalRulerColumn createLineNumberRulerColumn();
084:
085: boolean isQuickDiffEnabled();
086:
087: boolean isLineNumberRulerVisible();
088: }
089:
090: /** The contribution id of the line number / change ruler. */
091: public static final String ID = "org.eclipse.ui.editors.columns.linenumbers"; //$NON-NLS-1$
092:
093: private static final String FG_COLOR_KEY = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR;
094: private static final String BG_COLOR_KEY = AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND;
095: private static final String USE_DEFAULT_BG_KEY = AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT;
096: private final static String LINE_NUMBER_KEY = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER;
097: private final static String REVISION_ASK_BEFORE_QUICKDIFF_SWITCH_KEY = AbstractDecoratedTextEditorPreferenceConstants.REVISION_ASK_BEFORE_QUICKDIFF_SWITCH;
098:
099: /**
100: * The delegate and implemenation of the ruler.
101: */
102: private IVerticalRulerColumn fDelegate;
103: /**
104: * The annotation preferences.
105: */
106: private final MarkerAnnotationPreferences fAnnotationPreferences = EditorsPlugin
107: .getDefault().getMarkerAnnotationPreferences();
108:
109: /**
110: * Preference dispatcher that registers a single listener so we don't have to manage every
111: * single preference listener.
112: */
113: private PropertyEventDispatcher fDispatcher;
114: private ISourceViewer fViewer;
115: private ICompatibilityForwarder fForwarder;
116:
117: /*
118: * @see org.eclipse.jface.text.source.IVerticalRulerColumn#createControl(org.eclipse.jface.text.source.CompositeRuler, org.eclipse.swt.widgets.Composite)
119: */
120: public Control createControl(CompositeRuler parentRuler,
121: Composite parentControl) {
122: Assert.isTrue(fDelegate != null);
123: ITextViewer viewer = parentRuler.getTextViewer();
124: Assert.isLegal(viewer instanceof ISourceViewer);
125: fViewer = (ISourceViewer) viewer;
126: initialize();
127: Control control = fDelegate.createControl(parentRuler,
128: parentControl);
129: return control;
130: }
131:
132: /*
133: * @see org.eclipse.jface.text.source.IVerticalRulerColumn#getControl()
134: */
135: public Control getControl() {
136: return fDelegate.getControl();
137: }
138:
139: /*
140: * @see org.eclipse.jface.text.source.IVerticalRulerColumn#getWidth()
141: */
142: public int getWidth() {
143: return fDelegate.getWidth();
144: }
145:
146: /*
147: * @see org.eclipse.jface.text.source.IVerticalRulerColumn#redraw()
148: */
149: public void redraw() {
150: fDelegate.redraw();
151: }
152:
153: /*
154: * @see org.eclipse.jface.text.source.IVerticalRulerColumn#setFont(org.eclipse.swt.graphics.Font)
155: */
156: public void setFont(Font font) {
157: fDelegate.setFont(font);
158: }
159:
160: /*
161: * @see org.eclipse.jface.text.source.IVerticalRulerColumn#setModel(org.eclipse.jface.text.source.IAnnotationModel)
162: */
163: public void setModel(IAnnotationModel model) {
164: if (getQuickDiffPreference())
165: fDelegate.setModel(model);
166: }
167:
168: /*
169: * @see org.eclipse.jface.text.source.IVerticalRulerInfo#getLineOfLastMouseButtonActivity()
170: */
171: public int getLineOfLastMouseButtonActivity() {
172: if (fDelegate instanceof IVerticalRulerInfo)
173: ((IVerticalRulerInfo) fDelegate)
174: .getLineOfLastMouseButtonActivity();
175: return -1;
176: }
177:
178: /*
179: * @see org.eclipse.jface.text.source.IVerticalRulerInfo#toDocumentLineNumber(int)
180: */
181: public int toDocumentLineNumber(int y_coordinate) {
182: if (fDelegate instanceof IVerticalRulerInfo)
183: ((IVerticalRulerInfo) fDelegate)
184: .toDocumentLineNumber(y_coordinate);
185: return -1;
186: }
187:
188: /*
189: * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#addVerticalRulerListener(org.eclipse.jface.text.source.IVerticalRulerListener)
190: */
191: public void addVerticalRulerListener(IVerticalRulerListener listener) {
192: if (fDelegate instanceof IVerticalRulerInfoExtension)
193: ((IVerticalRulerInfoExtension) fDelegate)
194: .addVerticalRulerListener(listener);
195: }
196:
197: /*
198: * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#getHover()
199: */
200: public IAnnotationHover getHover() {
201: if (fDelegate instanceof IVerticalRulerInfoExtension)
202: return ((IVerticalRulerInfoExtension) fDelegate).getHover();
203: return null;
204: }
205:
206: /*
207: * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#getModel()
208: */
209: public IAnnotationModel getModel() {
210: if (fDelegate instanceof IVerticalRulerInfoExtension)
211: return ((IVerticalRulerInfoExtension) fDelegate).getModel();
212: return null;
213: }
214:
215: /*
216: * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#removeVerticalRulerListener(org.eclipse.jface.text.source.IVerticalRulerListener)
217: */
218: public void removeVerticalRulerListener(
219: IVerticalRulerListener listener) {
220: if (fDelegate instanceof IVerticalRulerInfoExtension)
221: ((IVerticalRulerInfoExtension) fDelegate)
222: .removeVerticalRulerListener(listener);
223: }
224:
225: /*
226: * @see org.eclipse.ui.texteditor.rulers.AbstractContributedRulerColumn#columnRemoved()
227: */
228: public void columnRemoved() {
229: if (fDispatcher != null) {
230: fDispatcher.dispose();
231: fDispatcher = null;
232: }
233: }
234:
235: private IPreferenceStore getPreferenceStore() {
236: return EditorsUI.getPreferenceStore();
237: }
238:
239: private ISharedTextColors getSharedColors() {
240: return EditorsUI.getSharedTextColors();
241: }
242:
243: /**
244: * Initializes the given line number ruler column from the preference store.
245: */
246: private void initialize() {
247: final IPreferenceStore store = getPreferenceStore();
248: if (store == null)
249: return;
250:
251: // initial set up
252: updateForegroundColor(store, fDelegate);
253: updateBackgroundColor(store, fDelegate);
254:
255: updateLineNumbersVisibility(fDelegate);
256: updateQuickDiffVisibility(fDelegate);
257: updateCharacterMode(store, fDelegate);
258: updateRevisionRenderingMode(store, fDelegate);
259: updateRevisionAuthorVisibility(store, fDelegate);
260: updateRevisionIdVisibility(store, fDelegate);
261:
262: Map annotationPrefs = getAnnotationPreferenceMap();
263: final AnnotationPreference changedPref = (AnnotationPreference) annotationPrefs
264: .get("org.eclipse.ui.workbench.texteditor.quickdiffChange"); //$NON-NLS-1$
265: final AnnotationPreference addedPref = (AnnotationPreference) annotationPrefs
266: .get("org.eclipse.ui.workbench.texteditor.quickdiffAddition"); //$NON-NLS-1$
267: final AnnotationPreference deletedPref = (AnnotationPreference) annotationPrefs
268: .get("org.eclipse.ui.workbench.texteditor.quickdiffDeletion"); //$NON-NLS-1$
269: updateChangedColor(changedPref, store, fDelegate);
270: updateAddedColor(addedPref, store, fDelegate);
271: updateDeletedColor(deletedPref, store, fDelegate);
272:
273: fDelegate.redraw();
274:
275: // listen to changes
276: fDispatcher = new PropertyEventDispatcher(store);
277:
278: fDispatcher.addPropertyChangeListener(FG_COLOR_KEY,
279: new IPropertyChangeListener() {
280: public void propertyChange(PropertyChangeEvent event) {
281: updateForegroundColor(store, fDelegate);
282: fDelegate.redraw();
283: }
284: });
285: IPropertyChangeListener backgroundHandler = new IPropertyChangeListener() {
286: public void propertyChange(PropertyChangeEvent event) {
287: updateBackgroundColor(store, fDelegate);
288: fDelegate.redraw();
289: }
290: };
291: fDispatcher.addPropertyChangeListener(BG_COLOR_KEY,
292: backgroundHandler);
293: fDispatcher.addPropertyChangeListener(USE_DEFAULT_BG_KEY,
294: backgroundHandler);
295:
296: fDispatcher.addPropertyChangeListener(LINE_NUMBER_KEY,
297: new IPropertyChangeListener() {
298: public void propertyChange(PropertyChangeEvent event) {
299: // only handle quick diff on/off information, but not ruler visibility (handled by AbstractDecoratedTextEditor)
300: updateLineNumbersVisibility(fDelegate);
301: }
302: });
303:
304: fDispatcher
305: .addPropertyChangeListener(
306: AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_CHARACTER_MODE,
307: new IPropertyChangeListener() {
308: public void propertyChange(
309: PropertyChangeEvent event) {
310: updateCharacterMode(store, fDelegate);
311: }
312: });
313:
314: fDispatcher
315: .addPropertyChangeListener(
316: AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE,
317: new IPropertyChangeListener() {
318: public void propertyChange(
319: PropertyChangeEvent event) {
320: updateRevisionRenderingMode(store,
321: fDelegate);
322: }
323: });
324:
325: fDispatcher
326: .addPropertyChangeListener(
327: AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_AUTHOR,
328: new IPropertyChangeListener() {
329: public void propertyChange(
330: PropertyChangeEvent event) {
331: updateRevisionAuthorVisibility(store,
332: fDelegate);
333: }
334: });
335:
336: fDispatcher
337: .addPropertyChangeListener(
338: AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_REVISION,
339: new IPropertyChangeListener() {
340: public void propertyChange(
341: PropertyChangeEvent event) {
342: updateRevisionIdVisibility(store,
343: fDelegate);
344: }
345: });
346:
347: fDispatcher
348: .addPropertyChangeListener(
349: AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON,
350: new IPropertyChangeListener() {
351: public void propertyChange(
352: PropertyChangeEvent event) {
353: updateQuickDiffVisibility(fDelegate);
354: }
355: });
356:
357: if (changedPref != null) {
358: fDispatcher.addPropertyChangeListener(changedPref
359: .getColorPreferenceKey(),
360: new IPropertyChangeListener() {
361: public void propertyChange(
362: PropertyChangeEvent event) {
363: updateChangedColor(changedPref, store,
364: fDelegate);
365: fDelegate.redraw();
366: }
367: });
368: }
369: if (addedPref != null) {
370: fDispatcher.addPropertyChangeListener(addedPref
371: .getColorPreferenceKey(),
372: new IPropertyChangeListener() {
373: public void propertyChange(
374: PropertyChangeEvent event) {
375: updateAddedColor(addedPref, store,
376: fDelegate);
377: fDelegate.redraw();
378: }
379: });
380: }
381: if (deletedPref != null) {
382: fDispatcher.addPropertyChangeListener(deletedPref
383: .getColorPreferenceKey(),
384: new IPropertyChangeListener() {
385: public void propertyChange(
386: PropertyChangeEvent event) {
387: updateDeletedColor(deletedPref, store,
388: fDelegate);
389: fDelegate.redraw();
390: }
391: });
392: }
393: }
394:
395: private Map getAnnotationPreferenceMap() {
396: Map annotationPrefs = new HashMap();
397: Iterator iter = fAnnotationPreferences
398: .getAnnotationPreferences().iterator();
399: while (iter.hasNext()) {
400: AnnotationPreference pref = (AnnotationPreference) iter
401: .next();
402: Object type = pref.getAnnotationType();
403: annotationPrefs.put(type, pref);
404: }
405: return annotationPrefs;
406: }
407:
408: private void updateForegroundColor(IPreferenceStore store,
409: IVerticalRulerColumn column) {
410: RGB rgb = getColorFromStore(store, FG_COLOR_KEY);
411: if (rgb == null)
412: rgb = new RGB(0, 0, 0);
413: ISharedTextColors sharedColors = getSharedColors();
414: if (column instanceof LineNumberRulerColumn)
415: ((LineNumberRulerColumn) column).setForeground(sharedColors
416: .getColor(rgb));
417: }
418:
419: private void updateBackgroundColor(IPreferenceStore store,
420: IVerticalRulerColumn column) {
421: // background color: same as editor, or system default
422: RGB rgb;
423: if (store.getBoolean(USE_DEFAULT_BG_KEY))
424: rgb = null;
425: else
426: rgb = getColorFromStore(store, BG_COLOR_KEY);
427: ISharedTextColors sharedColors = getSharedColors();
428: if (column instanceof LineNumberRulerColumn)
429: ((LineNumberRulerColumn) column).setBackground(sharedColors
430: .getColor(rgb));
431: }
432:
433: private void updateChangedColor(AnnotationPreference pref,
434: IPreferenceStore store, IVerticalRulerColumn column) {
435: if (pref != null && column instanceof IChangeRulerColumn) {
436: RGB rgb = getColorFromAnnotationPreference(store, pref);
437: ((IChangeRulerColumn) column)
438: .setChangedColor(getSharedColors().getColor(rgb));
439: }
440: }
441:
442: private void updateAddedColor(AnnotationPreference pref,
443: IPreferenceStore store, IVerticalRulerColumn column) {
444: if (pref != null && column instanceof IChangeRulerColumn) {
445: RGB rgb = getColorFromAnnotationPreference(store, pref);
446: ((IChangeRulerColumn) column)
447: .setAddedColor(getSharedColors().getColor(rgb));
448: }
449: }
450:
451: private void updateDeletedColor(AnnotationPreference pref,
452: IPreferenceStore store, IVerticalRulerColumn column) {
453: if (pref != null && column instanceof IChangeRulerColumn) {
454: RGB rgb = getColorFromAnnotationPreference(store, pref);
455: ((IChangeRulerColumn) column)
456: .setDeletedColor(getSharedColors().getColor(rgb));
457: }
458: }
459:
460: private void updateCharacterMode(IPreferenceStore store,
461: IVerticalRulerColumn column) {
462: if (column instanceof LineNumberChangeRulerColumn) {
463: LineNumberChangeRulerColumn lncrc = (LineNumberChangeRulerColumn) column;
464: lncrc
465: .setDisplayMode(store
466: .getBoolean(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_CHARACTER_MODE));
467: }
468: }
469:
470: private void updateLineNumbersVisibility(IVerticalRulerColumn column) {
471: if (column instanceof LineNumberChangeRulerColumn)
472: ((LineNumberChangeRulerColumn) column)
473: .showLineNumbers(getLineNumberPreference());
474: }
475:
476: private void updateRevisionRenderingMode(IPreferenceStore store,
477: IVerticalRulerColumn column) {
478: if (column instanceof IRevisionRulerColumnExtension) {
479: String option = store
480: .getString(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE);
481: RenderingMode[] modes = {
482: IRevisionRulerColumnExtension.AUTHOR,
483: IRevisionRulerColumnExtension.AGE,
484: IRevisionRulerColumnExtension.AUTHOR_SHADED_BY_AGE };
485: for (int i = 0; i < modes.length; i++) {
486: if (modes[i].name().equals(option)) {
487: ((IRevisionRulerColumnExtension) column)
488: .setRevisionRenderingMode(modes[i]);
489: return;
490: }
491: }
492: }
493: }
494:
495: private void updateRevisionAuthorVisibility(IPreferenceStore store,
496: IVerticalRulerColumn column) {
497: if (column instanceof IRevisionRulerColumnExtension) {
498: boolean show = store
499: .getBoolean(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_AUTHOR);
500: ((IRevisionRulerColumnExtension) column)
501: .showRevisionAuthor(show);
502: }
503: }
504:
505: private void updateRevisionIdVisibility(IPreferenceStore store,
506: IVerticalRulerColumn column) {
507: if (column instanceof IRevisionRulerColumnExtension) {
508: boolean show = store
509: .getBoolean(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_REVISION);
510: ((IRevisionRulerColumnExtension) column)
511: .showRevisionId(show);
512: }
513: }
514:
515: private void updateQuickDiffVisibility(IVerticalRulerColumn column) {
516: boolean show = getQuickDiffPreference();
517: if (show == isShowingChangeInformation())
518: return;
519:
520: if (show)
521: installChangeRulerModel(column);
522: else
523: uninstallChangeRulerModel(column);
524: }
525:
526: /**
527: * Returns whether the line number ruler column should be
528: * visible according to the preference store settings. Subclasses may override this
529: * method to provide a custom preference setting.
530: *
531: * @return <code>true</code> if the line numbers should be visible
532: */
533: private boolean getLineNumberPreference() {
534: if (fForwarder != null)
535: return fForwarder.isLineNumberRulerVisible();
536: IPreferenceStore store = getPreferenceStore();
537: return store != null ? store.getBoolean(LINE_NUMBER_KEY)
538: : false;
539: }
540:
541: /**
542: * Returns whether quick diff info should be visible upon opening an editor
543: * according to the preference store settings.
544: *
545: * @return <code>true</code> if the line numbers should be visible
546: */
547: private boolean getQuickDiffPreference() {
548: if (fForwarder != null)
549: return fForwarder.isQuickDiffEnabled();
550: IPreferenceStore store = getPreferenceStore();
551: boolean setting = store != null ? store
552: .getBoolean(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON)
553: : false;
554: if (!setting)
555: return false;
556:
557: boolean modifiable;
558: ITextEditor editor = getEditor();
559: if (editor instanceof ITextEditorExtension2) {
560: ITextEditorExtension2 ext = (ITextEditorExtension2) editor;
561: modifiable = ext.isEditorInputModifiable();
562: } else if (editor instanceof ITextEditorExtension) {
563: ITextEditorExtension ext = (ITextEditorExtension) editor;
564: modifiable = ext.isEditorInputReadOnly();
565: } else if (editor != null) {
566: modifiable = editor.isEditable();
567: } else {
568: modifiable = true;
569: }
570: return modifiable;
571: }
572:
573: /**
574: * Extracts the color preference for the given preference from the given store.
575: * If the given store indicates that the default value is to be used, or
576: * the value stored in the preferences store is <code>null</code>,
577: * the value is taken from the <code>AnnotationPreference</code>'s default
578: * color value.
579: * <p>
580: * The return value is
581: * </p>
582: *
583: * @param store the preference store
584: * @param pref the annotation preference
585: * @return the RGB color preference, not <code>null</code>
586: */
587: private static RGB getColorFromAnnotationPreference(
588: IPreferenceStore store, AnnotationPreference pref) {
589: String key = pref.getColorPreferenceKey();
590: RGB rgb = null;
591: if (store.contains(key)) {
592: if (store.isDefault(key))
593: rgb = pref.getColorPreferenceValue();
594: else
595: rgb = PreferenceConverter.getColor(store, key);
596: }
597: if (rgb == null)
598: rgb = pref.getColorPreferenceValue();
599: return rgb;
600: }
601:
602: private static RGB getColorFromStore(IPreferenceStore store,
603: String key) {
604: RGB rgb = null;
605: if (store.contains(key)) {
606: if (store.isDefault(key))
607: rgb = PreferenceConverter.getDefaultColor(store, key);
608: else
609: rgb = PreferenceConverter.getColor(store, key);
610: }
611: return rgb;
612: }
613:
614: /**
615: * Ensures that quick diff information is displayed and the quick diff provider is the one with
616: * the specified id. If a different quick diff provider is in use, the user may be asked whether
617: * he wants to switch.
618: *
619: * @param diffProviderId the quick diff provider id to use
620: * @return <code>true</code> if quick diff could be enabled for the given id,
621: * <code>false</code> otherwise
622: */
623: private boolean ensureQuickDiffProvider(String diffProviderId) {
624: if (!isShowingChangeInformation())
625: installChangeRulerModel(fDelegate); // FIXME pass provider id
626:
627: IAnnotationModel annotationModel = fViewer.getAnnotationModel();
628: IAnnotationModel oldDiffer = getDiffer();
629: if (oldDiffer == null && annotationModel != null)
630: return false; // quick diff is enabled, but no differ? not working for whatever reason
631:
632: if (annotationModel == null)
633: annotationModel = new AnnotationModel();
634: if (!(annotationModel instanceof IAnnotationModelExtension))
635: return false;
636:
637: QuickDiff util = new QuickDiff();
638: Object oldDifferId = util
639: .getConfiguredQuickDiffProvider(oldDiffer);
640: if (oldDifferId.equals(diffProviderId)) {
641: if (oldDiffer instanceof ILineDifferExtension)
642: ((ILineDifferExtension) oldDiffer).resume();
643: return true;
644: }
645:
646: // Check whether the desired provider is available at all
647: IAnnotationModel newDiffer = util
648: .createQuickDiffAnnotationModel(getEditor(),
649: diffProviderId);
650: if (util.getConfiguredQuickDiffProvider(newDiffer).equals(
651: oldDifferId)) {
652: if (oldDiffer instanceof ILineDifferExtension)
653: ((ILineDifferExtension) oldDiffer).resume();
654: return true;
655: }
656:
657: // quick diff is showing with the wrong provider - ask the user whether he wants to switch
658: IPreferenceStore store = EditorsUI.getPreferenceStore();
659: if (oldDiffer != null
660: && !store.getString(
661: REVISION_ASK_BEFORE_QUICKDIFF_SWITCH_KEY)
662: .equals(MessageDialogWithToggle.ALWAYS)) {
663: MessageDialogWithToggle toggleDialog = MessageDialogWithToggle
664: .openOkCancelConfirm(
665: fViewer.getTextWidget().getShell(),
666: RulerMessages.AbstractDecoratedTextEditor_revision_quickdiff_switch_title,
667: RulerMessages.AbstractDecoratedTextEditor_revision_quickdiff_switch_message,
668: RulerMessages.AbstractDecoratedTextEditor_revision_quickdiff_switch_rememberquestion,
669: true, store,
670: REVISION_ASK_BEFORE_QUICKDIFF_SWITCH_KEY);
671: if (toggleDialog.getReturnCode() != Window.OK)
672: return false;
673: }
674:
675: IAnnotationModelExtension modelExtension = (IAnnotationModelExtension) annotationModel;
676: modelExtension
677: .removeAnnotationModel(IChangeRulerColumn.QUICK_DIFF_MODEL_ID);
678:
679: modelExtension.addAnnotationModel(
680: IChangeRulerColumn.QUICK_DIFF_MODEL_ID, newDiffer);
681:
682: if (fDelegate instanceof IChangeRulerColumn)
683: ((IChangeRulerColumn) fDelegate).setModel(annotationModel); // picks up the new model attachment
684:
685: return true;
686: }
687:
688: /**
689: * Installs the differ annotation model with the current quick diff display.
690: *
691: * @param column the column to install the model on
692: */
693: private void installChangeRulerModel(IVerticalRulerColumn column) {
694: if (column instanceof IChangeRulerColumn) {
695: IAnnotationModel model = getAnnotationModelWithDiffer();
696: ((IChangeRulerColumn) column).setModel(model);
697: if (model != null) {
698: ISourceViewer viewer = fViewer;
699: if (viewer != null
700: && viewer.getAnnotationModel() == null)
701: viewer.showAnnotations(true);
702: }
703: }
704: }
705:
706: /**
707: * Uninstalls the differ annotation model from the current quick diff display.
708: *
709: * @param column the column to remove the model from
710: */
711: private void uninstallChangeRulerModel(IVerticalRulerColumn column) {
712: if (column instanceof IChangeRulerColumn)
713: ((IChangeRulerColumn) column).setModel(null);
714: IAnnotationModel model = getDiffer();
715: if (model instanceof ILineDifferExtension)
716: ((ILineDifferExtension) model).suspend();
717:
718: ISourceViewer viewer = fViewer;
719: if (viewer != null && viewer.getAnnotationModel() == null)
720: viewer.showAnnotations(false);
721: }
722:
723: /**
724: * Returns the annotation model that contains the quick diff annotation model.
725: * <p>
726: * Extracts the line differ from the displayed document's annotation model. If none can be found,
727: * a new differ is created and attached to the annotation model.</p>
728: *
729: * @return the annotation model that contains the line differ, or <code>null</code> if none could be found or created
730: * @see IChangeRulerColumn#QUICK_DIFF_MODEL_ID
731: */
732: private IAnnotationModel getAnnotationModelWithDiffer() {
733: ISourceViewer viewer = fViewer;
734: if (viewer == null)
735: return null;
736:
737: IAnnotationModel m = viewer.getAnnotationModel();
738: IAnnotationModelExtension model = null;
739: if (m instanceof IAnnotationModelExtension)
740: model = (IAnnotationModelExtension) m;
741:
742: IAnnotationModel differ = getDiffer();
743: // create diff model if it doesn't
744: if (differ == null) {
745: IPreferenceStore store = getPreferenceStore();
746: if (store != null) {
747: String defaultId = store
748: .getString(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_DEFAULT_PROVIDER);
749: differ = new QuickDiff()
750: .createQuickDiffAnnotationModel(getEditor(),
751: defaultId);
752: if (differ != null) {
753: if (model == null)
754: model = new AnnotationModel();
755: model.addAnnotationModel(
756: IChangeRulerColumn.QUICK_DIFF_MODEL_ID,
757: differ);
758: }
759: }
760: } else if (differ instanceof ILineDifferExtension2) {
761: if (((ILineDifferExtension2) differ).isSuspended())
762: ((ILineDifferExtension) differ).resume();
763: } else if (differ instanceof ILineDifferExtension) {
764: ((ILineDifferExtension) differ).resume();
765: }
766:
767: return (IAnnotationModel) model;
768: }
769:
770: /**
771: * Extracts the line differ from the displayed document's annotation model. If none can be found,
772: * <code>null</code> is returned.
773: *
774: * @return the line differ, or <code>null</code> if none could be found
775: */
776: private IAnnotationModel getDiffer() {
777: // get annotation model extension
778: ISourceViewer viewer = fViewer;
779: if (viewer == null)
780: return null;
781:
782: IAnnotationModel m = viewer.getAnnotationModel();
783: if (m == null && fDelegate instanceof IChangeRulerColumn)
784: m = ((IChangeRulerColumn) fDelegate).getModel();
785:
786: if (!(m instanceof IAnnotationModelExtension))
787: return null;
788:
789: IAnnotationModelExtension model = (IAnnotationModelExtension) m;
790:
791: // get diff model if it exists already
792: return model
793: .getAnnotationModel(IChangeRulerColumn.QUICK_DIFF_MODEL_ID);
794: }
795:
796: /**
797: * Sets the forwarder. Used by {@link AbstractDecoratedTextEditor} to maintain the contract of
798: * its {@link AbstractDecoratedTextEditor#createLineNumberRulerColumn} method.
799: *
800: * @param forwarder the forwarder
801: */
802: public void setForwarder(ICompatibilityForwarder forwarder) {
803: fForwarder = forwarder;
804: fDelegate = forwarder.createLineNumberRulerColumn();
805: }
806:
807: /**
808: * Initializes the given line number ruler column from the preference store.
809: *
810: * @param rulerColumn the ruler column to be initialized
811: */
812: public void initializeLineNumberRulerColumn(
813: LineNumberRulerColumn rulerColumn) {
814: IPreferenceStore store = getPreferenceStore();
815: if (store != null) {
816: updateForegroundColor(store, rulerColumn);
817: updateBackgroundColor(store, rulerColumn);
818: updateLineNumbersVisibility(rulerColumn);
819: rulerColumn.redraw();
820: }
821: }
822:
823: /**
824: * Returns <code>true</code> if the ruler is showing line numbers, <code>false</code> if it
825: * is only showing change information.
826: *
827: * @return <code>true</code> if line numbers are shown, <code>false</code> otherwise
828: */
829: public boolean isShowingLineNumbers() {
830: return fDelegate instanceof LineNumberChangeRulerColumn
831: && ((LineNumberChangeRulerColumn) fDelegate)
832: .isShowingLineNumbers();
833: }
834:
835: /**
836: * Returns <code>true</code> if the ruler is showing change information, <code>false</code>
837: * if it is only showing line numbers.
838: *
839: * @return <code>true</code> if change information is shown, <code>false</code> otherwise
840: */
841: public boolean isShowingChangeInformation() {
842: return fDelegate instanceof LineNumberChangeRulerColumn
843: && ((LineNumberChangeRulerColumn) fDelegate)
844: .isShowingChangeInformation();
845: }
846:
847: /**
848: * Shows revision information on the receiver.
849: *
850: * @param info the revision information to show
851: * @param quickDiffProviderId the id of the corresponding quick diff provider
852: */
853: public void showRevisionInformation(RevisionInformation info,
854: String quickDiffProviderId) {
855: if (!ensureQuickDiffProvider(quickDiffProviderId))
856: return;
857:
858: if (fDelegate instanceof IRevisionRulerColumn)
859: ((IRevisionRulerColumn) fDelegate)
860: .setRevisionInformation(info);
861: }
862:
863: /**
864: * Hides revision information.
865: */
866: public void hideRevisionInformation() {
867: if (fDelegate instanceof IRevisionRulerColumn)
868: ((IRevisionRulerColumn) fDelegate)
869: .setRevisionInformation(null);
870: }
871:
872: /**
873: * Returns <code>true</code> if the ruler is showing revision information, <code>false</code>
874: * if it is only showing line numbers.
875: *
876: * @return <code>true</code> if revision information is shown, <code>false</code> otherwise
877: */
878: public boolean isShowingRevisionInformation() {
879: if (fDelegate instanceof LineNumberChangeRulerColumn)
880: return ((LineNumberChangeRulerColumn) fDelegate)
881: .isShowingRevisionInformation();
882: return false;
883: }
884:
885: /**
886: * Returns the selection provider of the revision column, <code>null</code> if none is
887: * available.
888: *
889: * @return the revision selection provider
890: */
891: public ISelectionProvider getRevisionSelectionProvider() {
892: if (fDelegate instanceof IRevisionRulerColumnExtension)
893: return ((IRevisionRulerColumnExtension) fDelegate)
894: .getRevisionSelectionProvider();
895: return null;
896: }
897: }
|