home | career | drupal | java | mac | mysql | perl | scala | uml | unix

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*******************************************************************************
 * Copyright (c) 2006, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.texteditor;


import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;

import org.eclipse.core.runtime.Assert;

import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.window.Window;

import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.revisions.IRevisionRulerColumn;
import org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension;
import org.eclipse.jface.text.revisions.RevisionInformation;
import org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension.RenderingMode;
import org.eclipse.jface.text.source.AnnotationModel;
import org.eclipse.jface.text.source.CompositeRuler;
import org.eclipse.jface.text.source.IAnnotationHover;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.IAnnotationModelExtension;
import org.eclipse.jface.text.source.IChangeRulerColumn;
import org.eclipse.jface.text.source.ILineDifferExtension;
import org.eclipse.jface.text.source.ILineDifferExtension2;
import org.eclipse.jface.text.source.ISharedTextColors;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.IVerticalRulerColumn;
import org.eclipse.jface.text.source.IVerticalRulerInfo;
import org.eclipse.jface.text.source.IVerticalRulerInfoExtension;
import org.eclipse.jface.text.source.IVerticalRulerListener;
import org.eclipse.jface.text.source.LineNumberChangeRulerColumn;
import org.eclipse.jface.text.source.LineNumberRulerColumn;

import org.eclipse.ui.editors.text.EditorsUI;

import org.eclipse.ui.internal.editors.text.EditorsPlugin;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.ui.texteditor.AnnotationPreference;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.ITextEditorExtension;
import org.eclipse.ui.texteditor.ITextEditorExtension2;
import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
import org.eclipse.ui.texteditor.quickdiff.QuickDiff;
import org.eclipse.ui.texteditor.rulers.AbstractContributedRulerColumn;

/**
 * The line number ruler contribution. Encapsulates a {@link LineNumberChangeRulerColumn} as a
 * contribution to the <code>rulerColumns extension point. Instead of instantiating the
 * delegate itself, it calls <code>createLineNumberRulerColumn() in
 * {@link AbstractDecoratedTextEditor} via {@link ICompatibilityForwarder} to maintain compatibility
 * with previous releases.
 * 
 * @since 3.3
 */
public class LineNumberColumn extends AbstractContributedRulerColumn implements IVerticalRulerInfo, IVerticalRulerInfoExtension {
	/**
	 * Forwarder for preference checks and ruler creation. Needed to maintain the forwarded APIs in
	 * {@link AbstractDecoratedTextEditor}.
	 */
	public static interface ICompatibilityForwarder {
		IVerticalRulerColumn createLineNumberRulerColumn();
		boolean isQuickDiffEnabled();
		boolean isLineNumberRulerVisible();
	}
	
	/** The contribution id of the line number / change ruler. */
	public static final String ID= "org.eclipse.ui.editors.columns.linenumbers"; //$NON-NLS-1$

	private static final String FG_COLOR_KEY= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR;
	private static final String BG_COLOR_KEY= AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND;
	private static final String USE_DEFAULT_BG_KEY= AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT;
	private final static String LINE_NUMBER_KEY= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER;
	private final static String REVISION_ASK_BEFORE_QUICKDIFF_SWITCH_KEY= AbstractDecoratedTextEditorPreferenceConstants.REVISION_ASK_BEFORE_QUICKDIFF_SWITCH;

	/**
	 * The delegate and implemenation of the ruler.
	 */
	private IVerticalRulerColumn fDelegate;
	/**
	 * The annotation preferences.
	 */
	private final MarkerAnnotationPreferences fAnnotationPreferences= EditorsPlugin.getDefault().getMarkerAnnotationPreferences();

	/**
	 * Preference dispatcher that registers a single listener so we don't have to manage every
	 * single preference listener.
	 */
	private PropertyEventDispatcher fDispatcher;
	private ISourceViewer fViewer;
	private ICompatibilityForwarder fForwarder;

	/*
	 * @see org.eclipse.jface.text.source.IVerticalRulerColumn#createControl(org.eclipse.jface.text.source.CompositeRuler, org.eclipse.swt.widgets.Composite)
	 */
	public Control createControl(CompositeRuler parentRuler, Composite parentControl) {
		Assert.isTrue(fDelegate != null);
		ITextViewer viewer= parentRuler.getTextViewer();
		Assert.isLegal(viewer instanceof ISourceViewer);
		fViewer= (ISourceViewer) viewer;
		initialize();
		Control control= fDelegate.createControl(parentRuler, parentControl);
		return control;
	}

	/*
	 * @see org.eclipse.jface.text.source.IVerticalRulerColumn#getControl()
	 */
	public Control getControl() {
		return fDelegate.getControl();
	}

	/*
	 * @see org.eclipse.jface.text.source.IVerticalRulerColumn#getWidth()
	 */
	public int getWidth() {
		return fDelegate.getWidth();
	}

	/*
	 * @see org.eclipse.jface.text.source.IVerticalRulerColumn#redraw()
	 */
	public void redraw() {
		fDelegate.redraw();
	}

	/*
	 * @see org.eclipse.jface.text.source.IVerticalRulerColumn#setFont(org.eclipse.swt.graphics.Font)
	 */
	public void setFont(Font font) {
		fDelegate.setFont(font);
	}

	/*
	 * @see org.eclipse.jface.text.source.IVerticalRulerColumn#setModel(org.eclipse.jface.text.source.IAnnotationModel)
	 */
	public void setModel(IAnnotationModel model) {
		if (getQuickDiffPreference())
			fDelegate.setModel(model);
	}
	
	/*
	 * @see org.eclipse.jface.text.source.IVerticalRulerInfo#getLineOfLastMouseButtonActivity()
	 */
	public int getLineOfLastMouseButtonActivity() {
		if (fDelegate instanceof IVerticalRulerInfo)
			return ((IVerticalRulerInfo)fDelegate).getLineOfLastMouseButtonActivity();
		return -1;
	}

	/*
	 * @see org.eclipse.jface.text.source.IVerticalRulerInfo#toDocumentLineNumber(int)
	 */
	public int toDocumentLineNumber(int y_coordinate) {
		if (fDelegate instanceof IVerticalRulerInfo)
			return ((IVerticalRulerInfo)fDelegate).toDocumentLineNumber(y_coordinate);
		return -1;
	}

	/*
	 * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#addVerticalRulerListener(org.eclipse.jface.text.source.IVerticalRulerListener)
	 */
	public void addVerticalRulerListener(IVerticalRulerListener listener) {
		if (fDelegate instanceof IVerticalRulerInfoExtension)
			((IVerticalRulerInfoExtension) fDelegate).addVerticalRulerListener(listener);
	}

	/*
	 * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#getHover()
	 */
	public IAnnotationHover getHover() {
		if (fDelegate instanceof IVerticalRulerInfoExtension)
			return ((IVerticalRulerInfoExtension) fDelegate).getHover();
		return null;
	}

	/*
	 * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#getModel()
	 */
	public IAnnotationModel getModel() {
		if (fDelegate instanceof IVerticalRulerInfoExtension)
			return ((IVerticalRulerInfoExtension) fDelegate).getModel();
		return null;
	}

	/*
	 * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#removeVerticalRulerListener(org.eclipse.jface.text.source.IVerticalRulerListener)
	 */
	public void removeVerticalRulerListener(IVerticalRulerListener listener) {
		if (fDelegate instanceof IVerticalRulerInfoExtension)
			((IVerticalRulerInfoExtension) fDelegate).removeVerticalRulerListener(listener);
	}

	/*
	 * @see org.eclipse.ui.texteditor.rulers.AbstractContributedRulerColumn#columnRemoved()
	 */
	public void columnRemoved() {
		if (fDispatcher != null) {
			fDispatcher.dispose();
			fDispatcher= null;
		}
	}

	private IPreferenceStore getPreferenceStore() {
		return EditorsUI.getPreferenceStore();
	}

	private ISharedTextColors getSharedColors() {
		return EditorsUI.getSharedTextColors();
	}

	/**
	 * Initializes the given line number ruler column from the preference store.
	 */
	private void initialize() {
		final IPreferenceStore store= getPreferenceStore();
		if (store == null)
			return;

		// initial set up
		updateForegroundColor(store, fDelegate);
		updateBackgroundColor(store, fDelegate);
		
		updateLineNumbersVisibility(fDelegate);
		updateQuickDiffVisibility(fDelegate);
		updateCharacterMode(store, fDelegate);
		updateRevisionRenderingMode(store, fDelegate);
		updateRevisionAuthorVisibility(store, fDelegate);
		updateRevisionIdVisibility(store, fDelegate);

		Map annotationPrefs= getAnnotationPreferenceMap();
		final AnnotationPreference changedPref= (AnnotationPreference) annotationPrefs.get("org.eclipse.ui.workbench.texteditor.quickdiffChange"); //$NON-NLS-1$
		final AnnotationPreference addedPref= (AnnotationPreference) annotationPrefs.get("org.eclipse.ui.workbench.texteditor.quickdiffAddition"); //$NON-NLS-1$
		final AnnotationPreference deletedPref= (AnnotationPreference) annotationPrefs.get("org.eclipse.ui.workbench.texteditor.quickdiffDeletion"); //$NON-NLS-1$
		updateChangedColor(changedPref, store, fDelegate);
		updateAddedColor(addedPref, store, fDelegate);
		updateDeletedColor(deletedPref, store, fDelegate);

		fDelegate.redraw();

		// listen to changes
		fDispatcher= new PropertyEventDispatcher(store);

		fDispatcher.addPropertyChangeListener(FG_COLOR_KEY, new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent event) {
				updateForegroundColor(store, fDelegate);
				fDelegate.redraw();
			}
		});
		IPropertyChangeListener backgroundHandler= new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent event) {
				updateBackgroundColor(store, fDelegate);
				fDelegate.redraw();
			}
		};
		fDispatcher.addPropertyChangeListener(BG_COLOR_KEY, backgroundHandler);
		fDispatcher.addPropertyChangeListener(USE_DEFAULT_BG_KEY, backgroundHandler);

		fDispatcher.addPropertyChangeListener(LINE_NUMBER_KEY, new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent event) {
				// only handle quick diff on/off information, but not ruler visibility (handled by AbstractDecoratedTextEditor)
				updateLineNumbersVisibility(fDelegate);
			}
		});

		fDispatcher.addPropertyChangeListener(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_CHARACTER_MODE, new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent event) {
				updateCharacterMode(store, fDelegate);
			}
		});

		fDispatcher.addPropertyChangeListener(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE, new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent event) {
				updateRevisionRenderingMode(store, fDelegate);
			}
		});
		
		fDispatcher.addPropertyChangeListener(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_AUTHOR, new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent event) {
				updateRevisionAuthorVisibility(store, fDelegate);
			}
		});
		
		fDispatcher.addPropertyChangeListener(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_REVISION, new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent event) {
				updateRevisionIdVisibility(store, fDelegate);
			}
		});
		
		fDispatcher.addPropertyChangeListener(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON, new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent event) {
				updateQuickDiffVisibility(fDelegate);
			}
		});

		if (changedPref != null) {
			fDispatcher.addPropertyChangeListener(changedPref.getColorPreferenceKey(), new IPropertyChangeListener() {
				public void propertyChange(PropertyChangeEvent event) {
					updateChangedColor(changedPref, store, fDelegate);
					fDelegate.redraw();
				}
			});
		}
		if (addedPref != null) {
			fDispatcher.addPropertyChangeListener(addedPref.getColorPreferenceKey(), new IPropertyChangeListener() {
				public void propertyChange(PropertyChangeEvent event) {
					updateAddedColor(addedPref, store, fDelegate);
					fDelegate.redraw();
				}
			});
		}
		if (deletedPref != null) {
			fDispatcher.addPropertyChangeListener(deletedPref.getColorPreferenceKey(), new IPropertyChangeListener() {
				public void propertyChange(PropertyChangeEvent event) {
					updateDeletedColor(deletedPref, store, fDelegate);
					fDelegate.redraw();
				}
			});
		}
	}

	private Map getAnnotationPreferenceMap() {
		Map annotationPrefs= new HashMap();
		Iterator iter= fAnnotationPreferences.getAnnotationPreferences().iterator();
		while (iter.hasNext()) {
			AnnotationPreference pref= (AnnotationPreference) iter.next();
			Object type= pref.getAnnotationType();
			annotationPrefs.put(type, pref);
		}
		return annotationPrefs;
	}
	
	private void updateForegroundColor(IPreferenceStore store, IVerticalRulerColumn column) {
		RGB rgb=  getColorFromStore(store, FG_COLOR_KEY);
		if (rgb == null)
			rgb= new RGB(0, 0, 0);
		ISharedTextColors sharedColors= getSharedColors();
		if (column instanceof LineNumberRulerColumn)
			((LineNumberRulerColumn) column).setForeground(sharedColors.getColor(rgb));
	}
	
	private void updateBackgroundColor(IPreferenceStore store, IVerticalRulerColumn column) {
		// background color: same as editor, or system default
		RGB rgb;
		if (store.getBoolean(USE_DEFAULT_BG_KEY))
			rgb= null;
		else
			rgb= getColorFromStore(store, BG_COLOR_KEY);
		ISharedTextColors sharedColors= getSharedColors();
		if (column instanceof LineNumberRulerColumn)
			((LineNumberRulerColumn) column).setBackground(sharedColors.getColor(rgb));
	}

	private void updateChangedColor(AnnotationPreference pref, IPreferenceStore store, IVerticalRulerColumn column) {
		if (pref != null && column instanceof IChangeRulerColumn) {
			RGB rgb= getColorFromAnnotationPreference(store, pref);
			((IChangeRulerColumn) column).setChangedColor(getSharedColors().getColor(rgb));
		}
	}

	private void updateAddedColor(AnnotationPreference pref, IPreferenceStore store, IVerticalRulerColumn column) {
		if (pref != null && column instanceof IChangeRulerColumn) {
			RGB rgb= getColorFromAnnotationPreference(store, pref);
			((IChangeRulerColumn) column).setAddedColor(getSharedColors().getColor(rgb));
		}
	}
	
	private void updateDeletedColor(AnnotationPreference pref, IPreferenceStore store, IVerticalRulerColumn column) {
		if (pref != null && column instanceof IChangeRulerColumn) {
			RGB rgb= getColorFromAnnotationPreference(store, pref);
			((IChangeRulerColumn) column).setDeletedColor(getSharedColors().getColor(rgb));
		}
	}
	
	private void updateCharacterMode(IPreferenceStore store, IVerticalRulerColumn column) {
		if (column instanceof LineNumberChangeRulerColumn) {
			LineNumberChangeRulerColumn lncrc= (LineNumberChangeRulerColumn) column;
			lncrc.setDisplayMode(store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_CHARACTER_MODE));
		}
	}

	private void updateLineNumbersVisibility(IVerticalRulerColumn column) {
		if (column instanceof LineNumberChangeRulerColumn)
			((LineNumberChangeRulerColumn) column).showLineNumbers(getLineNumberPreference());
	}
	
	private void updateRevisionRenderingMode(IPreferenceStore store, IVerticalRulerColumn column) {
		if (column instanceof IRevisionRulerColumnExtension) {
			String option= store.getString(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_RENDERING_MODE);
			RenderingMode[] modes= { IRevisionRulerColumnExtension.AUTHOR, IRevisionRulerColumnExtension.AGE, IRevisionRulerColumnExtension.AUTHOR_SHADED_BY_AGE };
			for (int i= 0; i < modes.length; i++) {
				if (modes[i].name().equals(option)) {
					((IRevisionRulerColumnExtension) column).setRevisionRenderingMode(modes[i]);
					return;
				}
			}
		}
	}
	
	private void updateRevisionAuthorVisibility(IPreferenceStore store, IVerticalRulerColumn column) {
		if (column instanceof IRevisionRulerColumnExtension) {
			boolean show= store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_AUTHOR);
			((IRevisionRulerColumnExtension) column).showRevisionAuthor(show);
		}
	}
	
	private void updateRevisionIdVisibility(IPreferenceStore store, IVerticalRulerColumn column) {
		if (column instanceof IRevisionRulerColumnExtension) {
			boolean show= store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.REVISION_RULER_SHOW_REVISION);
			((IRevisionRulerColumnExtension) column).showRevisionId(show);
		}
	}
	
	private void updateQuickDiffVisibility(IVerticalRulerColumn column) {
		boolean show= getQuickDiffPreference();
		if (show == isShowingChangeInformation())
			return;
		
		if (show)
			installChangeRulerModel(column);
		else
			uninstallChangeRulerModel(column);
	}
	
	/**
	 * Returns whether the line number ruler column should be
	 * visible according to the preference store settings. Subclasses may override this
	 * method to provide a custom preference setting.
	 *
	 * @return <code>true if the line numbers should be visible
	 */
	private boolean getLineNumberPreference() {
		if (fForwarder != null)
			return fForwarder.isLineNumberRulerVisible();
		IPreferenceStore store= getPreferenceStore();
		return store != null ? store.getBoolean(LINE_NUMBER_KEY) : false;
	}
	
	/**
	 * Returns whether quick diff info should be visible upon opening an editor
	 * according to the preference store settings.
	 *
	 * @return <code>true if the line numbers should be visible
	 */
	private boolean getQuickDiffPreference() {
		if (fForwarder != null)
			return fForwarder.isQuickDiffEnabled();
		IPreferenceStore store= getPreferenceStore();
		boolean setting= store != null ? store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON) : false;
		if (!setting)
			return false;
		
		boolean modifiable;
		ITextEditor editor= getEditor();
		if (editor instanceof ITextEditorExtension2) {
			ITextEditorExtension2 ext= (ITextEditorExtension2) editor;
			modifiable= ext.isEditorInputModifiable();
		} else if (editor instanceof ITextEditorExtension) {
			ITextEditorExtension ext= (ITextEditorExtension) editor;
			modifiable= ext.isEditorInputReadOnly();
		} else if (editor != null) {
			modifiable= editor.isEditable();
		} else {
			modifiable= true;
		}
		return modifiable;
	}

	/**
	 * Extracts the color preference for the given preference from the given store.
	 * If the given store indicates that the default value is to be used, or
	 * the value stored in the preferences store is <code>null,
	 * the value is taken from the <code>AnnotationPreference's default
	 * color value.
	 * <p>
	 * The return value is
	 * </p>
	 *
	 * @param store the preference store
	 * @param pref the annotation preference
	 * @return the RGB color preference, not <code>null
	 */
	private static RGB getColorFromAnnotationPreference(IPreferenceStore store, AnnotationPreference pref) {
		String key= pref.getColorPreferenceKey();
		RGB rgb= null;
		if (store.contains(key)) {
			if (store.isDefault(key))
				rgb= pref.getColorPreferenceValue();
			else
				rgb= PreferenceConverter.getColor(store, key);
		}
		if (rgb == null)
			rgb= pref.getColorPreferenceValue();
		return rgb;
	}
	
	private static RGB getColorFromStore(IPreferenceStore store, String key) {
		RGB rgb= null;
		if (store.contains(key)) {
			if (store.isDefault(key))
				rgb= PreferenceConverter.getDefaultColor(store, key);
			else
				rgb= PreferenceConverter.getColor(store, key);
		}
		return rgb;
	}
	
	/**
	 * Ensures that quick diff information is displayed and the quick diff provider is the one with
	 * the specified id. If a different quick diff provider is in use, the user may be asked whether
	 * he wants to switch.
	 * 
	 * @param diffProviderId the quick diff provider id to use
	 * @return <code>true if quick diff could be enabled for the given id,
	 *         <code>false otherwise
	 */
	private boolean ensureQuickDiffProvider(String diffProviderId) {
		if (!isShowingChangeInformation())
			installChangeRulerModel(fDelegate); // FIXME pass provider id
		
		IAnnotationModel annotationModel= fViewer.getAnnotationModel();
		IAnnotationModel oldDiffer= getDiffer();
		if (oldDiffer == null && annotationModel != null)
			return false; // quick diff is enabled, but no differ? not working for whatever reason

		if (annotationModel == null)
			annotationModel= new AnnotationModel();
		if (!(annotationModel instanceof IAnnotationModelExtension))
			return false;

		QuickDiff util= new QuickDiff();
		Object oldDifferId= util.getConfiguredQuickDiffProvider(oldDiffer);
		if (oldDifferId.equals(diffProviderId)) {
			if (oldDiffer instanceof ILineDifferExtension)
				((ILineDifferExtension) oldDiffer).resume();
			return true;
		}

		// Check whether the desired provider is available at all
		IAnnotationModel newDiffer= util.createQuickDiffAnnotationModel(getEditor(), diffProviderId);
		if (util.getConfiguredQuickDiffProvider(newDiffer).equals(oldDifferId)) {
			if (oldDiffer instanceof ILineDifferExtension)
				((ILineDifferExtension) oldDiffer).resume();
				return true;
		}
		
		// quick diff is showing with the wrong provider - ask the user whether he wants to switch
		IPreferenceStore store= EditorsUI.getPreferenceStore();
		if (oldDiffer != null && !store.getString(REVISION_ASK_BEFORE_QUICKDIFF_SWITCH_KEY).equals(MessageDialogWithToggle.ALWAYS)) {
			MessageDialogWithToggle toggleDialog= MessageDialogWithToggle.openOkCancelConfirm(
					fViewer.getTextWidget().getShell(),
					RulerMessages.AbstractDecoratedTextEditor_revision_quickdiff_switch_title,
					RulerMessages.AbstractDecoratedTextEditor_revision_quickdiff_switch_message,
					RulerMessages.AbstractDecoratedTextEditor_revision_quickdiff_switch_rememberquestion,
					true,
					store,
					REVISION_ASK_BEFORE_QUICKDIFF_SWITCH_KEY);
			if (toggleDialog.getReturnCode() != Window.OK)
				return false;
		}
		
		IAnnotationModelExtension modelExtension=(IAnnotationModelExtension) annotationModel;
		modelExtension.removeAnnotationModel(IChangeRulerColumn.QUICK_DIFF_MODEL_ID);
		

		modelExtension.addAnnotationModel(IChangeRulerColumn.QUICK_DIFF_MODEL_ID, newDiffer);
		
		if (fDelegate instanceof IChangeRulerColumn)
			((IChangeRulerColumn) fDelegate).setModel(annotationModel); // picks up the new model attachment
		
		return true;
	}

	/**
	 * Installs the differ annotation model with the current quick diff display.
	 * 
	 * @param column the column to install the model on
	 */
	private void installChangeRulerModel(IVerticalRulerColumn column) {
		if (column instanceof IChangeRulerColumn) {
			IAnnotationModel model= getAnnotationModelWithDiffer();
			((IChangeRulerColumn) column).setModel(model);
			if (model != null) {
				ISourceViewer viewer= fViewer;
				if (viewer != null && viewer.getAnnotationModel() == null)
					viewer.showAnnotations(true);
				}
		}
	}

	/**
	 * Uninstalls the differ annotation model from the current quick diff display.
	 * 
	 * @param column the column to remove the model from
	 */
	private void uninstallChangeRulerModel(IVerticalRulerColumn column) {
		if (column instanceof IChangeRulerColumn)
			((IChangeRulerColumn) column).setModel(null);
		IAnnotationModel model= getDiffer();
		if (model instanceof ILineDifferExtension)
			((ILineDifferExtension) model).suspend();

		ISourceViewer viewer= fViewer;
		if (viewer != null && viewer.getAnnotationModel() == null)
			viewer.showAnnotations(false);
	}

	/**
	 * Returns the annotation model that contains the quick diff annotation model.
	 * <p>
	 * Extracts the line differ from the displayed document's annotation model. If none can be found,
	 * a new differ is created and attached to the annotation model.</p>
	 *
	 * @return the annotation model that contains the line differ, or <code>null if none could be found or created
	 * @see IChangeRulerColumn#QUICK_DIFF_MODEL_ID
	 */
	private IAnnotationModel getAnnotationModelWithDiffer() {
		ISourceViewer viewer= fViewer;
		if (viewer == null)
			return null;
		
		IAnnotationModel m= viewer.getAnnotationModel();
		IAnnotationModelExtension model= null;
		if (m instanceof IAnnotationModelExtension)
			model= (IAnnotationModelExtension) m;
		
		IAnnotationModel differ= getDiffer();
		// create diff model if it doesn't
		if (differ == null) {
			IPreferenceStore store= getPreferenceStore();
			if (store != null) {
				String defaultId= store.getString(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_DEFAULT_PROVIDER);
				differ= new QuickDiff().createQuickDiffAnnotationModel(getEditor(), defaultId);
				if (differ != null) {
					if (model == null)
						model= new AnnotationModel();
					model.addAnnotationModel(IChangeRulerColumn.QUICK_DIFF_MODEL_ID, differ);
				}
			}
		} else if (differ instanceof ILineDifferExtension2) {
			if (((ILineDifferExtension2) differ).isSuspended())
				((ILineDifferExtension) differ).resume();
		} else if (differ instanceof ILineDifferExtension) {
			((ILineDifferExtension) differ).resume();
		}
		
		return (IAnnotationModel)model;
	}

	/**
	 * Extracts the line differ from the displayed document's annotation model. If none can be found,
	 * <code>null is returned.
	 *
	 * @return the line differ, or <code>null if none could be found
	 */
	private IAnnotationModel getDiffer() {
		// get annotation model extension
		ISourceViewer viewer= fViewer;
		if (viewer == null)
			return null;

		IAnnotationModel m= viewer.getAnnotationModel();
		if (m == null && fDelegate instanceof IChangeRulerColumn)
			m= ((IChangeRulerColumn)fDelegate).getModel();
		
		if (!(m instanceof IAnnotationModelExtension))
			return null;
		
		IAnnotationModelExtension model= (IAnnotationModelExtension)m;

		// get diff model if it exists already
		return model.getAnnotationModel(IChangeRulerColumn.QUICK_DIFF_MODEL_ID);
	}

	/**
	 * Sets the forwarder. Used by {@link AbstractDecoratedTextEditor} to maintain the contract of
	 * its {@link AbstractDecoratedTextEditor#createLineNumberRulerColumn} method.
	 * 
	 * @param forwarder the forwarder
	 */
	public void setForwarder(ICompatibilityForwarder forwarder) {
		fForwarder= forwarder;
		fDelegate= forwarder.createLineNumberRulerColumn();
	}

	/**
	 * Initializes the given line number ruler column from the preference store.
	 *
	 * @param rulerColumn the ruler column to be initialized
	 */
	public void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) {
		IPreferenceStore store= getPreferenceStore();
		if (store != null) {
			updateForegroundColor(store, rulerColumn);
			updateBackgroundColor(store, rulerColumn);
			updateLineNumbersVisibility(rulerColumn);
			rulerColumn.redraw();
		}
	}

	/**
	 * Returns <code>true if the ruler is showing line numbers, false if it
	 * is only showing change information.
	 * 
	 * @return <code>true if line numbers are shown, false otherwise
	 */
	public boolean isShowingLineNumbers() {
		return fDelegate instanceof LineNumberChangeRulerColumn && ((LineNumberChangeRulerColumn) fDelegate).isShowingLineNumbers();
	}
	
	/**
	 * Returns <code>true if the ruler is showing change information, false
	 * if it is only showing line numbers.
	 * 
	 * @return <code>true if change information is shown, false otherwise
	 */
	public boolean isShowingChangeInformation() {
		return fDelegate instanceof LineNumberChangeRulerColumn && ((LineNumberChangeRulerColumn) fDelegate).isShowingChangeInformation();
	}

	/**
	 * Shows revision information on the receiver.
	 * 
	 * @param info the revision information to show
	 * @param quickDiffProviderId the id of the corresponding quick diff provider
	 */
	public void showRevisionInformation(RevisionInformation info, String quickDiffProviderId) {
		if (!ensureQuickDiffProvider(quickDiffProviderId))
			return;

		if (fDelegate instanceof IRevisionRulerColumn)
			((IRevisionRulerColumn) fDelegate).setRevisionInformation(info);
	}

	/**
	 * Hides revision information.
	 */
	public void hideRevisionInformation() {
		if (fDelegate instanceof IRevisionRulerColumn)
			((IRevisionRulerColumn) fDelegate).setRevisionInformation(null);
	}
	
	/**
	 * Returns <code>true if the ruler is showing revision information, false
	 * if it is only showing line numbers.
	 * 
	 * @return <code>true if revision information is shown, false otherwise
	 */
	public boolean isShowingRevisionInformation() {
		if (fDelegate instanceof LineNumberChangeRulerColumn)
			return ((LineNumberChangeRulerColumn) fDelegate).isShowingRevisionInformation();
		return false;
	}

	/**
	 * Returns the selection provider of the revision column, <code>null if none is
	 * available.
	 * 
	 * @return the revision selection provider
	 */
	public ISelectionProvider getRevisionSelectionProvider() {
		if (fDelegate instanceof IRevisionRulerColumnExtension)
			return ((IRevisionRulerColumnExtension) fDelegate).getRevisionSelectionProvider();
		return null;
	}
}

new blog posts

 

Copyright 1998-2014 Alvin Alexander, alvinalexander.com
All Rights Reserved.