/*******************************************************************************
 * Copyright (c) 2005, 2007 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
 *     Matt Chapman - initial version
 *******************************************************************************/
package org.eclipse.ajdt.internal.ui.diff;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.eclipse.ajdt.core.model.AJModel;
import org.eclipse.ajdt.core.model.AJProjectModel;
import org.eclipse.ajdt.core.model.AJRelationship;
import org.eclipse.ajdt.core.model.AJRelationshipManager;
import org.eclipse.ajdt.core.model.AJRelationshipType;
import org.eclipse.ajdt.core.model.ModelComparison;
import org.eclipse.ajdt.internal.ui.help.AspectJUIHelp;
import org.eclipse.ajdt.internal.ui.help.IAJHelpContextIds;
import org.eclipse.ajdt.internal.ui.preferences.AspectJPreferences;
import org.eclipse.ajdt.internal.ui.resources.AspectJImages;
import org.eclipse.ajdt.internal.ui.text.UIMessages;
import org.eclipse.ajdt.ui.AspectJUIPlugin;
import org.eclipse.contribution.xref.internal.ui.utils.XRefUIUtils;
import org.eclipse.contribution.xref.ui.XReferenceUIPlugin;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.help.IContextProvider;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableCursor;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.part.ViewPart;

import com.ibm.icu.text.Collator;

/**
 * Crosscutting changes view which shows the results of comparing two structure
 * models (one of which might be the one for the current build)
 */
public class ChangesView extends ViewPart {

	private ChangesViewFilterAction filterAction;

	private Action propagateToggleAction;
	
	private Action linkWithBuildToggleAction;

	private Action comparisonReferenceAction;

	public static final String CROSSCUTTING_VIEW_ID = "org.eclipse.ajdt.ui.diff.ChangesView"; //$NON-NLS-1$

	public static final String MAP_FILE_EXT = "ajmap"; //$NON-NLS-1$

	public static final String DOT_MAP_FILE_EXT = "." + MAP_FILE_EXT; //$NON-NLS-1$

	public static final String CURRENT_BUILD = UIMessages.changesView_currentBuild;

	private Table table;

	private TableCursor cursor;
	
	private int selectedRow, selectedColumn;
	
	private IJavaElement[] sourceElements;

	private IJavaElement[] targetElements;

	private int lastMouseDownTime;

	private IProject currFromProject, currToProject;

	private IJavaElement currFromEl, currToEl;
	
	private String currFromName, currToName;

	private static Image incomingImage = null;

	private static Image outgoingImage = null;

	private boolean propagateUp = false;

	private boolean comparePrev = true;
	
	public static final String REF_LAST_INC = "last build"; //$NON-NLS-1$
	
	public static final String REF_LAST_FULL = "last full build"; //$NON-NLS-1$

	/* maps a project to a string defining the comparison reference point */
	private static Map fReferencePointMap = new HashMap();
	
	private static final int EMPTY = 0;
	private static final int COMPARING_FILES = 1;
	private static final int COMPARING_ELEMENTS = 2;
	
	private int compareMode = EMPTY;
	
	private ILabelProvider labelProvider;

	public ChangesView() {
		labelProvider = new DecoratingLabelProvider(
				new JavaElementLabelProvider(), AspectJUIPlugin.getDefault()
						.getWorkbench().getDecoratorManager().getLabelDecorator());
	}

	public static void refresh(boolean force, IProject project) {
		IWorkbenchWindow w = AspectJUIPlugin.getDefault().getWorkbench()
			.getActiveWorkbenchWindow();
		if (w == null) {
			return;
		}
		IViewPart view = w.getActivePage().findView(
						ChangesView.CROSSCUTTING_VIEW_ID);
		if (view instanceof ChangesView) {
			ChangesView changesView = (ChangesView) view;
			if (changesView.comparePrev) {
				changesView.compareWithEarlierBuild(project);
			} else {
				if (changesView.compareMode == COMPARING_FILES) {
					changesView.refreshIfCurrentBuild(force);
				} else if (changesView.compareMode == COMPARING_ELEMENTS) {
					changesView.refresh();
				}
			}
		}
	}

	private void refresh() {
		compareElements(currFromEl, currToEl);
	}
	
	private void refreshIfCurrentBuild(boolean force) {
		if ((currFromName != null) && (currToName != null)) {
			if (force || currFromName.equals(CURRENT_BUILD)
					|| currToName.equals(CURRENT_BUILD)) {
				compareProjects(currFromProject, currFromName, currToProject,
						currToName);
			}
		}
	}

	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	public void createPartControl(Composite parent) {
		table = new Table(parent, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION);
		table.setLayoutData(new GridData(GridData.FILL_BOTH));
		table.setLinesVisible(false);
		table.setHeaderVisible(true);
		String[] titles = {
				UIMessages.changesView_table_column1,
				UIMessages.changesView_table_column2,
				UIMessages.changesView_table_column3,
				UIMessages.changesView_table_column4
		};
		for (int i = 0; i < titles.length; i++) {
			TableColumn column = new TableColumn(table, SWT.NONE);
			column.setText(titles[i]);
		}
		for (int c = 0; c < titles.length; c++) {
			table.getColumn(c).pack();
			final int col = c;
			// click column headers to sort
			table.getColumn(c).addListener(SWT.Selection, new Listener() {
				public void handleEvent(Event e) {
					TableItem[] items = table.getItems();
					Collator collator = Collator.getInstance(Locale
							.getDefault());
					for (int i = 1; i < items.length; i++) {
						String value1 = items[i].getText(col);
						for (int j = 0; j < i; j++) {
							String value2 = items[j].getText(col);
							if (collator.compare(value1, value2) < 0) {
								String[] values = { items[i].getText(0),
										items[i].getText(1),
										items[i].getText(2),
										items[i].getText(3) };
								Image[] icons = { items[i].getImage(0),
										items[i].getImage(1),
										items[i].getImage(2),
										items[i].getImage(3) };
								items[i].dispose();
								TableItem item = new TableItem(table, SWT.NONE,
										j);
								item.setText(values);
								item.setImage(icons);
								items = table.getItems();

								// change stored elements to match
								IJavaElement temp = sourceElements[i];
								System.arraycopy(sourceElements, j,
										sourceElements, j + 1, i - j);
								sourceElements[j] = temp;
								temp = targetElements[i];
								System.arraycopy(targetElements, j,
										targetElements, j + 1, i - j);
								targetElements[j] = temp;
								break;
							}
						}
					}
				}
			});
		}

		// keyboard selection
		cursor = new TableCursor(table, SWT.SINGLE);
		cursor.addSelectionListener(new SelectionAdapter() {
			// when the TableEditor is over a cell, select the corresponding row
			// in the table
			public void widgetSelected(SelectionEvent e) {
				table.setSelection(new TableItem[] { cursor.getRow() });
			}

			// when the user hits "ENTER" in the TableCursor, navigate to that
			// element
			public void widgetDefaultSelected(SelectionEvent e) {
				navigateTo(table.indexOf(cursor.getRow()), cursor.getColumn());
			}
		});

		// mouse selection
		table.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				lastMouseDownTime = e.time;
			}
		});
		cursor.addMouseListener(new MouseAdapter() {
			public void mouseDown(MouseEvent event) {
				if ((event.time - lastMouseDownTime) < Display.getDefault()
						.getDoubleClickTime()) {
					mouseDoubleClick(event);
				}
			}

			public void mouseDoubleClick(MouseEvent event) {
				Rectangle b = cursor.getBounds();
				Point pt = new Point(b.x + event.x, b.y + event.y);
				TableItem row = table.getItem(pt);
				if (row == null) {
					return;
				}
				for (int i = 0; i < table.getColumnCount(); i++) {
					Rectangle rect = row.getBounds(i);
					if (rect.contains(pt)) {
						navigateTo(table.indexOf(row), i);
					}
				}
			}
		});
		
		restorePersistedSettings();
		makeActions();
		contributeToActionBars();

		// ensure focus goes to the cursor not the table
		table.addFocusListener(new FocusListener() {
			public void focusGained(FocusEvent e) {
				cursor.setVisible(true);
				cursor.setFocus();
			}

			public void focusLost(FocusEvent e) {
			}
		});
		cursor.addFocusListener(new FocusListener() {
			public void focusGained(FocusEvent e) {
			}

			public void focusLost(FocusEvent e) {
				if (cursor.getRow() != null) {
					selectedColumn = cursor.getColumn();
					selectedRow = table.indexOf(cursor.getRow());
				}
				cursor.setVisible(false);
				table.setSelection(-1);
			}
		});
		
		// resize columns when view is resized
		table.addControlListener(new ControlAdapter() {
			public void controlResized(ControlEvent e) {
				resizeColumns();
			}
		});
		
		// Add an empty ISelectionProvider so that this view works with dynamic help (bug 104331)
		getSite().setSelectionProvider(new ISelectionProvider() {
			public void addSelectionChangedListener(ISelectionChangedListener listener) {
			}
			public ISelection getSelection() {
				return null;
			}
			public void removeSelectionChangedListener(ISelectionChangedListener listener) {
			}
			public void setSelection(ISelection selection) {
			}
		});
	}

	private void navigateTo(int row, int column) {
		// can only navigate to elements (columns 1 and 3)
		if ((column == 1) && (sourceElements != null)
				&& (row < sourceElements.length)) {
			// source element
			XRefUIUtils.revealInEditor(sourceElements[row]);
		} else if ((column == 3) && (targetElements != null)
				&& (row < targetElements.length)) {
			// target element
			XRefUIUtils.revealInEditor(targetElements[row]);
		}
	}

	public void dispose() {
		super.dispose();
		persistSettings();
		
		sourceElements = null;
		targetElements = null;
		currFromProject = null;
		currFromName = null;
		currToProject = null;
		currToName = null;

		if (incomingImage != null) {
			incomingImage.dispose();
			incomingImage = null;
		}
		if (outgoingImage != null) {
			outgoingImage.dispose();
			outgoingImage = null;
		}
	}

	private void persistSettings() {
		IPreferenceStore pstore = AspectJUIPlugin.getDefault()
				.getPreferenceStore();
		if (!pstore.contains(AspectJPreferences.CHANGES_VIEW_PROPAGATE_UP)) {
			pstore.setDefault(AspectJPreferences.CHANGES_VIEW_PROPAGATE_UP, false);
		}
		pstore.setValue(AspectJPreferences.CHANGES_VIEW_PROPAGATE_UP, propagateUp);

		if (!pstore.contains(AspectJPreferences.CHANGES_VIEW_COMPARE_PREV)) {
			pstore.setDefault(AspectJPreferences.CHANGES_VIEW_COMPARE_PREV, true);
		}
		pstore.setValue(AspectJPreferences.CHANGES_VIEW_COMPARE_PREV, comparePrev);
		AspectJUIPlugin.getDefault().savePluginPreferences();
	}

	private void restorePersistedSettings() {
		IPreferenceStore pstore = AspectJUIPlugin.getDefault()
				.getPreferenceStore();
		if (pstore.contains(AspectJPreferences.CHANGES_VIEW_PROPAGATE_UP)) {
			propagateUp = pstore.getBoolean(AspectJPreferences.CHANGES_VIEW_PROPAGATE_UP);
		}
		
		if (pstore.contains(AspectJPreferences.CHANGES_VIEW_COMPARE_PREV)) {
			comparePrev = pstore.getBoolean(AspectJPreferences.CHANGES_VIEW_COMPARE_PREV);
		}
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		if (table.getItemCount() > 0) {
			cursor.setVisible(true);
			if (selectedColumn >= 0 && selectedColumn < table.getColumnCount()
					&& selectedRow >= 0 && selectedRow < table.getItemCount()) {
				cursor.setSelection(selectedRow,selectedColumn);
			} else {
				cursor.setSelection(0,0);
			}
			cursor.setFocus();
		}
	}

	private void updateDescription(String fromName, String toName, int remove,
			int total) {
		if (remove == total) {
			setContentDescription(NLS.bind(UIMessages.changesView_description, fromName, toName));
		} else {
			setContentDescription(NLS.bind(UIMessages.changesView_description, fromName, toName)
					+ " " + NLS.bind(UIMessages.changesView_filter_dialog_showingXofY, new Integer(remove).toString(), new Integer(total).toString() )); //$NON-NLS-1$
		}
	}

	private AJProjectModel getModelFromName(IProject project, String name) {
		if (name.equals(CURRENT_BUILD)) {
			return AJModel.getInstance().getModelForProject(project);
		}
		IPath mapFile = project.getFile(name).getLocation();
		AJProjectModel model = new AJProjectModel(project);
		boolean success = model.loadModel(mapFile);
		if (!success) {
			return null;
		}
		return model;
	}
	
	private static Image getIncomingImage() {
		if (incomingImage == null) {
			incomingImage = AspectJImages.CHANGES_ADDED.getImageDescriptor()
					.createImage();
		}
		return incomingImage;
	}

	private static Image getOutgoingImage() {
		if (outgoingImage == null) {
			outgoingImage = AspectJImages.CHANGES_REMOVED.getImageDescriptor()
					.createImage();
		}
		return outgoingImage;
	}

	private List filterRelationshipList(List relationshipList) {
		List filteredList = new ArrayList();
		for (Iterator iter = relationshipList.iterator(); iter.hasNext();) {
			AJRelationship element = (AJRelationship) iter.next();
			if (!filterAction.getCheckedList().contains(
					element.getRelationship().getDisplayName())) {
				filteredList.add(element);
			}
		}
		return filteredList;
	}

	public void compareProjects(IProject fromProject, String fromName,
			IProject toProject, String toName) {
		compareMode = COMPARING_FILES;
		
		currFromProject = fromProject;
		currFromName = fromName;
		currToProject = toProject;
		currToName = toName;

		AJProjectModel fromModel = getModelFromName(fromProject, fromName);
		AJProjectModel toModel = getModelFromName(toProject, toName);
		if ((fromModel == null) || (toModel == null)) {
			return;
		}
		
		List[] ret = new ModelComparison(propagateUp).compareProjects(fromModel, toModel);
		
		boolean filterAdded = filterAction.getCheckedList().contains(
				UIMessages.changesView_filter_added_rels);
		boolean filterRemoved = filterAction.getCheckedList().contains(
				UIMessages.changesView_filter_removed_rels);
		List addedList = filterAdded ? new ArrayList()
				: filterRelationshipList(ret[0]);
		List removedList = filterRemoved ? new ArrayList()
				: filterRelationshipList(ret[1]);

		int totalNoRelationships = ret[0].size() + ret[1].size();
		updateDescription(fromName, toName, (addedList.size() + removedList
				.size()), totalNoRelationships);

		updateTable(addedList, removedList, fromModel, toModel);
	}
	
	public void compareElements(IJavaElement fromEl, IJavaElement toEl) {
		compareMode = COMPARING_ELEMENTS;
		currFromEl = fromEl;
		currToEl = toEl;
		
		IProject fromProject = fromEl.getResource().getProject();
		IProject toProject = toEl.getResource().getProject();

		AJProjectModel fromModel = AJModel.getInstance().getModelForProject(
				fromProject);
		AJProjectModel toModel = AJModel.getInstance().getModelForProject(
				toProject);

		List[] ret = new ModelComparison(propagateUp).compareElements(fromModel, toModel,
				fromEl, toEl);
		boolean filterAdded = filterAction.getCheckedList().contains(
				UIMessages.changesView_filter_added_rels);
		boolean filterRemoved = filterAction.getCheckedList().contains(
				UIMessages.changesView_filter_removed_rels);
		List addedList = filterAdded ? new ArrayList()
				: filterRelationshipList(ret[0]);
		List removedList = filterRemoved ? new ArrayList()
				: filterRelationshipList(ret[1]);

		int totalNoRelationships = ret[0].size() + ret[1].size();
		updateDescription(fromEl.getElementName(), toEl.getElementName(),
				(addedList.size() + removedList.size()), totalNoRelationships);

		updateTable(addedList, removedList, fromModel, toModel);
	}
	
	public void compareWithEarlierBuild(IProject project) {
		String ref = getReferencePoint(project);
		if (ref.endsWith(DOT_MAP_FILE_EXT)) { // map file
			compareProjects(project,ref,project,CURRENT_BUILD);
			return;
		}
				
		currFromProject = project;
		AJProjectModel fromModel;
		if (ref.equals(REF_LAST_FULL)) {
			currFromName = UIMessages.changesView_ComparisonReference_last_full;
			fromModel = AJModel.getInstance().getPreviousFullBuildModel(project);
		} else {
			currFromName = UIMessages.changesView_ComparisonReference_last_inc;
			fromModel = AJModel.getInstance().getPreviousModel(project);
		}
		
		currToProject = project;
		currToName = UIMessages.changesView_currentBuild;		
		
		AJProjectModel toModel = AJModel.getInstance().getModelForProject(
				project);
		if ((fromModel == null) || (toModel == null)) {
			return;
		}
		
		List[] ret = new ModelComparison(propagateUp).compareProjects(fromModel, toModel);
		
		boolean filterAdded = filterAction.getCheckedList().contains(
				UIMessages.changesView_filter_added_rels);
		boolean filterRemoved = filterAction.getCheckedList().contains(
				UIMessages.changesView_filter_removed_rels);
		List addedList = filterAdded ? new ArrayList()
				: filterRelationshipList(ret[0]);
		List removedList = filterRemoved ? new ArrayList()
				: filterRelationshipList(ret[1]);

		int totalNoRelationships = ret[0].size() + ret[1].size();
		updateDescription(currFromName, currToName, (addedList.size() + removedList
				.size()), totalNoRelationships);

		updateTable(addedList, removedList, fromModel, toModel);
	}
	
	private void updateTable(List addedList, List removedList,
			AJProjectModel fromModel, AJProjectModel toModel) {
		int numEntries = addedList.size() + removedList.size();
		sourceElements = new IJavaElement[numEntries];
		targetElements = new IJavaElement[numEntries];

		// update table with results
		table.removeAll();
		int rowCount = 0;

		// added relationships
		for (Iterator iter = addedList.iterator(); iter.hasNext();) {
			AJRelationship rel = (AJRelationship) iter.next();
			String sourceName = toModel.getJavaElementLinkName(rel.getSource());
			String targetName = toModel.getJavaElementLinkName(rel.getTarget());
			TableItem item = new TableItem(table, SWT.NONE);
			item.setText(0, UIMessages.changesView_table_added);
			item.setImage(0, getIncomingImage());
			item.setText(1, sourceName);
			item.setImage(1, labelProvider.getImage(rel.getSource()));
			item.setText(2, rel.getRelationship().getDisplayName());
			item.setImage(2, XReferenceUIPlugin.getDefault()
					.getXReferenceImage());
			item.setText(3, targetName);
			item.setImage(3, labelProvider.getImage(rel.getTarget()));

			sourceElements[rowCount] = rel.getSource();
			targetElements[rowCount] = rel.getTarget();
			rowCount++;
		}
		// removed relationships
		for (Iterator iter = removedList.iterator(); iter.hasNext();) {
			AJRelationship rel = (AJRelationship) iter.next();
			String sourceName = fromModel.getJavaElementLinkName(rel
					.getSource());
			String targetName = fromModel.getJavaElementLinkName(rel
					.getTarget());
			TableItem item = new TableItem(table, SWT.NONE);
			item.setText(0, UIMessages.changesView_table_removed);
			item.setImage(0, getOutgoingImage());
			item.setText(1, sourceName);
			item.setImage(1, labelProvider.getImage(rel.getSource()));
			item.setText(2, rel.getRelationship().getDisplayName());
			item.setImage(2, XReferenceUIPlugin.getDefault()
					.getXReferenceImage());
			item.setText(3, targetName);
			item.setImage(3, labelProvider.getImage(rel.getTarget()));

			sourceElements[rowCount] = rel.getSource();
			targetElements[rowCount] = rel.getTarget();
			rowCount++;
		}

		// adjust column sizes as necessary
		for (int i = 0; i < table.getColumnCount(); i++) {
			table.getColumn(i).pack();
		}
		resizeColumns();
	}

	private void resizeColumns() {
		if (table == null) {
			return;
		}
		if (table.getColumnCount() < 4) {
			return;
		}

		// split available space between columns 1 and 3 (source and target
		// elements)
		int w = table.getClientArea().width - table.getColumn(0).getWidth()
				- table.getColumn(2).getWidth();
		table.getColumn(1).setWidth(w / 2);
		table.getColumn(3).setWidth(w - w / 2);
	}

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalToolBar(bars.getToolBarManager());
	}

	private void fillLocalToolBar(IToolBarManager manager) {
		filterAction.fillActionBars(getViewSite().getActionBars());
		manager.add(propagateToggleAction);
		manager.add(linkWithBuildToggleAction);
		manager.add(comparisonReferenceAction);
	}

	private void makeActions() {
		propagateToggleAction = new Action() {
			public int getStyle() {
				return IAction.AS_CHECK_BOX;
			}

			public void run() {
				propagateUp = !propagateUp;
				refresh(true,currFromProject);
			}
		};
		propagateToggleAction.setText(UIMessages.changesView_propagate_message);
		propagateToggleAction
				.setToolTipText(UIMessages.changesView_propagate_tooltip);
		propagateToggleAction.setImageDescriptor(AspectJImages.PROPAGATE_UP.getImageDescriptor());
		propagateToggleAction.setChecked(propagateUp);
		
		comparisonReferenceAction = new ComparisonReferenceDropDownAction();
		linkWithBuildToggleAction = new Action() {
			public int getStyle() {
				return IAction.AS_CHECK_BOX;
			}

			public void run() {
				comparePrev = !comparePrev;
				comparisonReferenceAction.setEnabled(comparePrev);
			}
		};
		linkWithBuildToggleAction.setText(UIMessages.changesView_compare_message);
		linkWithBuildToggleAction
				.setToolTipText(UIMessages.changesView_compare_tooltip);
		linkWithBuildToggleAction.setImageDescriptor(AspectJImages.PROPAGATE_UP.getImageDescriptor());
		JavaPluginImages.setLocalImageDescriptors(linkWithBuildToggleAction, "synced.gif"); //$NON-NLS-1$
		linkWithBuildToggleAction.setChecked(comparePrev);
		
		AJRelationshipType[] relationshipTypes = AJRelationshipManager.getAllRelationshipTypes();

		List populatingList = new ArrayList();
		for (int i = 0; i < relationshipTypes.length; i++) {
			populatingList.add(relationshipTypes[i].getDisplayName());
		}
		populatingList.add(UIMessages.changesView_filter_added_rels);
		populatingList.add(UIMessages.changesView_filter_removed_rels);

		// list of relationships to filter out by default
		List defaultFilterList = new ArrayList();
		defaultFilterList.add(AJRelationshipManager.ADVISED_BY.getDisplayName());
		defaultFilterList.add(AJRelationshipManager.ASPECT_DECLARATIONS.getDisplayName());
		defaultFilterList.add(AJRelationshipManager.MATCHES_DECLARE.getDisplayName());
		defaultFilterList.add(AJRelationshipManager.ANNOTATED_BY.getDisplayName());
		defaultFilterList.add(AJRelationshipManager.SOFTENED_BY.getDisplayName());
		defaultFilterList.add(AJRelationshipManager.USES_POINTCUT.getDisplayName());
		defaultFilterList.add(AJRelationshipManager.POINTCUT_USED_BY.getDisplayName());

		List checkedList = new ArrayList();
		if (checkedList.size() == 0) {
			checkedList = new ArrayList(defaultFilterList);
		}
		
		String dlogTitle = UIMessages.changesView_filter_dialog_title;
		String dlogMessage = UIMessages.changesView_filter_dialog_message;
		filterAction = new ChangesViewFilterAction(getSite().getShell(),
				populatingList, checkedList, defaultFilterList, dlogTitle,
				dlogMessage, UIMessages.changesView_filter_action_tooltip);
	}
	
	public Object getAdapter(Class key) {
		if (key.equals(IContextProvider.class)) {
			return AspectJUIHelp.getHelpContextProvider(this, IAJHelpContextIds.CROSSCUTTING_COMPARISON_VIEW);
		}
		return super.getAdapter(key);
	}

	public static String getReferencePoint(IProject project) {
		String ref = (String)fReferencePointMap.get(project);
		if (ref != null) {
			return ref;
		}
		return REF_LAST_INC; // default
	}

	public static void setReferencePoint(IProject project, String label) {
		fReferencePointMap.put(project,label);
	}
}
