/*******************************************************************************
 * Copyright (c) 2006, 2012 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
 *     Eugene Kuleshov <eu@md.pp.ru> - Bug 153932 [History] Custom hyperlink detectors for comments in History view
 *     Brock Janiczak (brockj@tpg.com.au) - Bug 181899 CVS History wrongly ordered
 *******************************************************************************/

package org.eclipse.team.internal.ccvs.ui;

import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.*;

import org.eclipse.compare.*;
import org.eclipse.compare.structuremergeviewer.DiffNode;
import org.eclipse.compare.structuremergeviewer.ICompareInput;
import org.eclipse.core.resources.*;
import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
import org.eclipse.core.resources.mapping.ResourceChangeValidator;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.*;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.*;
import org.eclipse.jface.text.revisions.Revision;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.viewers.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.history.*;
import org.eclipse.team.core.variants.IResourceVariant;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.Command;
import org.eclipse.team.internal.ccvs.core.client.Update;
import org.eclipse.team.internal.ccvs.core.filehistory.*;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.resources.RemoteFile;
import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
import org.eclipse.team.internal.ccvs.ui.actions.CVSAction;
import org.eclipse.team.internal.ccvs.ui.actions.MoveRemoteTagAction;
import org.eclipse.team.internal.ccvs.ui.operations.*;
import org.eclipse.team.internal.core.history.LocalFileRevision;
import org.eclipse.team.internal.ui.TeamUIMessages;
import org.eclipse.team.internal.ui.Utils;
import org.eclipse.team.internal.ui.actions.*;
import org.eclipse.team.internal.ui.history.*;
import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
import org.eclipse.team.ui.history.*;
import org.eclipse.team.ui.synchronize.SaveableCompareEditorInput;
import org.eclipse.ui.*;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.progress.IProgressConstants;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;

import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.Calendar;

public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryCompareAdapter {
	
	/* private */ ICVSFile file;
	/* private */ ICVSFile previousFile;
	/* private */ IFileRevision currentFileRevision;
	private ITypedElement fileElement;
	
	// cached for efficiency
	/* private */ CVSFileHistory cvsFileHistory;
	/* private */IFileRevision[] entries;

	/* private */CVSHistoryTableProvider historyTableProvider;

	private Composite tagAndTextComposite;
	private Composite searchComposite;
	
	/* private */TreeViewer treeViewer;
	/* private */TextViewer textViewer;
	/* private */TableViewer tagViewer;

	/* private */CompareRevisionAction compareAction;
	/* private */OpenRevisionAction openAction;
	private OpenWithMenu openWithMenu;
	
	private CVSHistoryFilterAction  cvsHistoryFilter;
	private IAction toggleTextAction;
	private IAction toggleTextWrapAction;
	private IAction toggleListAction;
	private IAction toggleFilterAction;
	private IAction toggleSearchAction;
	private TextViewerAction copyAction;
	private TextViewerAction selectAllAction;
	private Action getContentsAction;
	private Action getRevisionAction;
	private Action refreshAction;
	/**
	 * Allows copying the tag name to the clipboard
	 */
	private TableViewerAction copyTagAction;
	
	private Action tagWithExistingAction;
	private Action localMode;
	private Action remoteMode;
	private Action remoteLocalMode;
	private Action groupByDateMode;
	private Action collapseAll;
	private Action compareModeAction;
	
	private SashForm sashForm;
	private SashForm innerSashForm;
	private SashForm searchSashForm;
	
	private Image branchImage;
	private Image versionImage;

	private IDialogSettings settings;

	protected IFileRevision currentSelection;

	/* private */RefreshCVSFileHistory  refreshCVSFileHistoryJob;

	/* private */boolean shutdown = false;

	/* private */boolean localFilteredOut = false;
	/* private */boolean remoteFilteredOut = false;
	
	private HistoryResourceListener resourceListener;
	
	//toggle constants for default click action
	private boolean compareMode = false;
	
	//filter constants
	public final static int REMOTE_LOCAL_MODE = 0;
	public final static int REMOTE_MODE = 1;
	public final static int LOCAL_MODE = 2;

	// page settings keys
	private final static String SASH_WEIGHTS = "SASH_WEIGHTS"; //$NON-NLS-1$
	private final static String INNER_SASH_WEIGHTS = "INNER_SASH_WEIGHTS"; //$NON-NLS-1$
	private final static String SASH_WEIGHTS_SEPARATOR = ";"; //$NON-NLS-1$
	private final static String SORT_ORDER_KEY = "SORT_ORDER"; //$NON-NLS-1$

	// page settings section name
	private static final String CVS_HISTORY_PAGE_SECTION = CVSHistoryPage.class.getName();

	//current filter mode
	private int currentFilerMode = 0;
	
	//text field used for search
	private Text searchField;
	
	//current tag list sort order.
	private boolean sortTagsAscending;

	// listener registered on the book this page is contained
	private DisposeListener disposeListener;

	//grouping on
	private boolean groupingOn;
	private CVSHistoryFilter historyFilter;
	private CVSHistorySearchFilter searchFilter;
	private RevisionAnnotationController rulerSelectionListener;
	
	private int refreshRequest = 0;
	private DateFormat dateTimeFormat;
	private String description;
	
	public CVSHistoryPage(Object object) {
		this.file = getCVSFile(object);

		IDialogSettings viewsSettings = CVSUIPlugin.getPlugin()
				.getDialogSettings();
		settings = viewsSettings.getSection(CVS_HISTORY_PAGE_SECTION);
		if (settings == null) {
			settings = viewsSettings.addNewSection(CVS_HISTORY_PAGE_SECTION);
		}
		sortTagsAscending= settings.get(SORT_ORDER_KEY) == null || settings.getBoolean(SORT_ORDER_KEY);
	}

	/**
	 * Action to sort the tag list ascending or descending.
	 */
	final class SortTagsAction extends Action {
		
		private boolean sortAscending;
		
		public SortTagsAction(boolean sortAscending) {
			super(
				sortAscending
					? CVSUIMessages.CVSHistoryPage_SortTagsAscendingAction
					: CVSUIMessages.CVSHistoryPage_SortTagsDescendingAction,
				IAction.AS_RADIO_BUTTON);
			setChecked(sortAscending == sortTagsAscending);
			this.sortAscending = sortAscending;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.action.Action#run()
		 */
		public void run() {
			sortTagsAscending = sortAscending;
			tagViewer.refresh();
		}
	}


	public void createControl(Composite parent) {
		initializeImages();
		
		sashForm = new SashForm(parent, SWT.VERTICAL);
		sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
		
		treeViewer = createTree(sashForm);
		
		tagAndTextComposite = new Composite(sashForm, SWT.NONE);
		tagAndTextComposite.setLayout(new FillLayout());
		innerSashForm = new SashForm(tagAndTextComposite, SWT.HORIZONTAL);
		tagViewer = createTagTable(innerSashForm);
		textViewer = createText(innerSashForm);
		
		searchComposite = new Composite(sashForm, SWT.NONE);
		searchComposite.setLayout(new FillLayout());
		searchSashForm = new SashForm(searchComposite, SWT.HORIZONTAL);
		//Find field
		searchField = new Text(searchSashForm, SWT.SEARCH);
		searchField.setMessage(CVSUIMessages.CVSHistoryPage_EnterSearchTerm);
		final SearchHistoryTable searchHistoryTable = new SearchHistoryTable();
		searchField.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e){
				Display.getDefault().timerExec(1000, searchHistoryTable);
			}
		});

		contributeActions();
		setViewerVisibility();

		int[] weights = loadSashWeights(SASH_WEIGHTS);
		sashForm.setWeights(weights.length == 3 ? weights : new int[] { 65, 20,
				15 });
		int[] innerWeights = loadSashWeights(INNER_SASH_WEIGHTS);
		innerSashForm.setWeights(innerWeights.length == 2 ? innerWeights
				: new int[] { 50, 50 });

		IHistoryPageSite parentSite = getHistoryPageSite();
		if (parentSite != null && parentSite instanceof DialogHistoryPageSite && treeViewer != null)
			parentSite.setSelectionProvider(treeViewer);
		
		resourceListener = new HistoryResourceListener();
		ResourcesPlugin.getWorkspace().addResourceChangeListener(resourceListener, IResourceChangeEvent.POST_CHANGE);
		
		PlatformUI.getWorkbench().getHelpSystem().setHelp(sashForm, IHelpContextIds.RESOURCE_HISTORY_VIEW);

		disposeListener = new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				saveState();
			}
		};
		parent.addDisposeListener(disposeListener);
	}

	private void saveState() {
		saveSashWeights(SASH_WEIGHTS, sashForm.getWeights());
		saveSashWeights(INNER_SASH_WEIGHTS, innerSashForm.getWeights());
		historyTableProvider.saveColumnLayout();
		settings.put(SORT_ORDER_KEY, sortTagsAscending);
	}

	private int[] loadSashWeights(String key) {
		String value = settings.get(key);
		if (value == null) {
			return new int[0];
		}
		String weigths[] = value.split(SASH_WEIGHTS_SEPARATOR);
		int result[] = new int[weigths.length];
		for (int i = 0; i < weigths.length; i++) {
			try {
				result[i] = Integer.parseInt(weigths[i]);
			} catch (NumberFormatException e) {
				return new int[0];
			}
		}
		return result;
	}

	private void saveSashWeights(String key, int[] weights) {
		StringBuffer value = new StringBuffer();
		for (int i = 0; i < weights.length; i++) {
			value = value.append(weights[i] + SASH_WEIGHTS_SEPARATOR);
		}
		settings.put(key, value.toString());
	}

	private TextViewer createText(SashForm parent) {
    SourceViewer result = new SourceViewer(parent, null, null, true, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.READ_ONLY);
    result.getTextWidget().setIndent(2);
    result.configure(new TextSourceViewerConfiguration(EditorsUI.getPreferenceStore()) {
      protected Map getHyperlinkDetectorTargets(ISourceViewer sourceViewer) {
        return Collections.singletonMap("org.eclipse.ui.DefaultTextEditor", //$NON-NLS-1$
            new IAdaptable() {
              public Object getAdapter(Class adapter) {
                if(adapter==IFile.class && getInput() instanceof IFile) {
                  return getInput();
                } else if(adapter==IFileHistory.class && getInput() instanceof IFileHistory) {
                  return getInput();
                }
                return Platform.getAdapterManager().getAdapter(CVSHistoryPage.this, adapter);
              }
            });
      }
    });

    result.addSelectionChangedListener(new ISelectionChangedListener() {
      public void selectionChanged(SelectionChangedEvent event) {
        copyAction.update();
      }
    });
    result.setTextDoubleClickStrategy(
                new DefaultTextDoubleClickStrategy(),
                IDocument.DEFAULT_CONTENT_TYPE);
		result.activatePlugins();
		return result;
	}

	private TableViewer createTagTable(SashForm parent) {
		Table table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);
		TableViewer result = new TableViewer(table);
		TableLayout layout = new TableLayout();
		layout.addColumnData(new ColumnWeightData(100));
		table.setLayout(layout);
		result.setContentProvider(new SimpleContentProvider() {
			public Object[] getElements(Object inputElement) {
				if (inputElement == null)
					return new Object[0];
				ITag[] tags = (ITag[]) inputElement;
				return tags;
			}
		});
		result.setLabelProvider(new LabelProvider() {
			public Image getImage(Object element) {
				if (element == null)
					return null;
				ITag tag = (ITag) element;
				if (!(tag instanceof CVSTag))
					return null;
				
				switch (((CVSTag)tag).getType()) {
					case CVSTag.BRANCH:
					case CVSTag.HEAD:
						return branchImage;
					case CVSTag.VERSION:
						return versionImage;
				}
				return null;
			}

			public String getText(Object element) {
				return ((ITag) element).getName();
			}
		});
		result.setComparator(new ViewerComparator() {
			public int compare(Viewer viewer, Object e1, Object e2) {
				if (!(e1 instanceof ITag) || !(e2 instanceof ITag))
					return super.compare(viewer, e1, e2);
				CVSTag tag1 = (CVSTag) e1;
				CVSTag tag2 = (CVSTag) e2;
				int type1 = tag1.getType();
				 int type2 = tag2.getType();
				 if (type1 != type2) {
				 return type2 - type1;
				 }
				if (sortTagsAscending)
					return super.compare(viewer, tag1, tag2);
				else
					return super.compare(viewer, tag2, tag1);
			}
		});
		result.addSelectionChangedListener(new ISelectionChangedListener() {

			public void selectionChanged(SelectionChangedEvent event) {
				copyTagAction.setEnabled(false);
				if (event.getSelection() instanceof StructuredSelection) {
					if (((StructuredSelection) event.getSelection()).getFirstElement() != null) {
						copyTagAction.setEnabled(true);
					}
				}
				
			}
			
		});
		return result;
	}

	public void setFocus() {
		sashForm.setFocus();
		if (refreshRequest != 0) {
			refresh(refreshRequest);
			refreshRequest = 0;
		}
	}

	protected void contributeActions() {
		CVSUIPlugin plugin = CVSUIPlugin.getPlugin();

		//Refresh
		refreshAction = new Action(CVSUIMessages.HistoryView_refreshLabel, plugin.getImageDescriptor(ICVSUIConstants.IMG_REFRESH_ENABLED)) {
			public void run() {
				refresh();
			}
		};
		refreshAction.setToolTipText(CVSUIMessages.HistoryView_refresh);
		refreshAction.setDisabledImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_REFRESH_DISABLED));
		refreshAction.setHoverImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_REFRESH));

		//Local Mode
		final IPreferenceStore store = CVSUIPlugin.getPlugin().getPreferenceStore();
		localMode =  new Action(CVSUIMessages.CVSHistoryPage_LocalModeAction, plugin.getImageDescriptor(ICVSUIConstants.IMG_LOCALMODE)) {
			public void run() {
				if (isChecked()){
					store.setValue(ICVSUIConstants.PREF_REVISION_MODE, LOCAL_MODE);
					updateFilterMode(LOCAL_MODE);
				} else
					setChecked(true);
			}
		};
		localMode.setToolTipText(CVSUIMessages.CVSHistoryPage_LocalModeTooltip);
		localMode.setDisabledImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_LOCALMODE_DISABLED));
		localMode.setHoverImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_LOCALMODE));

		//Remote Mode
		remoteMode =  new Action(CVSUIMessages.CVSHistoryPage_RemoteModeAction, plugin.getImageDescriptor(ICVSUIConstants.IMG_REMOTEMODE)) {
			public void run() {
				if (isChecked()){
					store.setValue(ICVSUIConstants.PREF_REVISION_MODE, REMOTE_MODE);
					updateFilterMode(REMOTE_MODE);
				} else
					setChecked(true);
			}
		};
		remoteMode.setToolTipText(CVSUIMessages.CVSHistoryPage_RemoteModeTooltip);
		remoteMode.setDisabledImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_REMOTEMODE_DISABLED));
		remoteMode.setHoverImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_REMOTEMODE));
		
		//Remote + Local Mode
		remoteLocalMode =  new Action(CVSUIMessages.CVSHistoryPage_CombinedModeAction, plugin.getImageDescriptor(ICVSUIConstants.IMG_LOCALREMOTE_MODE)) {
			public void run() {
				if (isChecked()){
					store.setValue(ICVSUIConstants.PREF_REVISION_MODE, REMOTE_LOCAL_MODE);
					updateFilterMode(REMOTE_LOCAL_MODE);
				} else
					setChecked(true);
			}
		};
		remoteLocalMode.setToolTipText(CVSUIMessages.CVSHistoryPage_CombinedModeTooltip);
		remoteLocalMode.setDisabledImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_LOCALREMOTE_MODE_DISABLED));
		remoteLocalMode.setHoverImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_LOCALREMOTE_MODE));
		
		//set the inital filter to both remote and local
		updateFilterMode(store.getInt(ICVSUIConstants.PREF_REVISION_MODE));
		
		//Group by Date
		groupByDateMode = new Action(CVSUIMessages.CVSHistoryPage_GroupByDate, CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_DATES_CATEGORY)){
			public void run() {
				groupingOn = !groupingOn;
				store.setValue(ICVSUIConstants.PREF_GROUPBYDATE_MODE, groupingOn);
				refreshHistory(false, false, CVSFileHistory.REFRESH_LOCAL | CVSFileHistory.REFRESH_REMOTE);
			}
		};
		groupingOn = store.getBoolean(ICVSUIConstants.PREF_GROUPBYDATE_MODE);
		groupByDateMode.setChecked(groupingOn);
		groupByDateMode.setToolTipText(CVSUIMessages.CVSHistoryPage_GroupByDate);
		groupByDateMode.setDisabledImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_DATES_CATEGORY));
		groupByDateMode.setHoverImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_DATES_CATEGORY));
		
		//Collapse All
		collapseAll =  new Action(CVSUIMessages.CVSHistoryPage_CollapseAllAction, plugin.getImageDescriptor(ICVSUIConstants.IMG_COLLAPSE_ALL)) {
			public void run() {
				treeViewer.collapseAll();
			}
		};
		collapseAll.setToolTipText(CVSUIMessages.CVSHistoryPage_CollapseAllTooltip);
		collapseAll.setDisabledImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_COLLAPSE_ALL));
		collapseAll.setHoverImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_COLLAPSE_ALL));
		
		//Compare Mode Action
		compareModeAction = new Action(CVSUIMessages.CVSHistoryPage_CompareModeToggleAction,plugin.getImageDescriptor(ICVSUIConstants.IMG_COMPARE_VIEW)) {
			public void run() {
				compareMode = !compareMode;
				compareModeAction.setChecked(compareMode);
			}
		};
		compareModeAction.setToolTipText(CVSUIMessages.CVSHistoryPage_CompareModeTooltip);
		compareModeAction.setDisabledImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_COMPARE_VIEW));
		compareModeAction.setHoverImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_COMPARE_VIEW));
		compareModeAction.setChecked(false);
		
		// Click Compare action
		compareAction = new CompareRevisionAction(CVSUIMessages.CVSHistoryPage_CompareRevisionAction, this);
		compareAction.setEnabled(!treeViewer.getSelection().isEmpty());
		treeViewer.getTree().addSelectionListener(new SelectionAdapter(){
			public void widgetSelected(SelectionEvent e) {
				//update the current
				compareAction.setCurrentFileRevision(getCurrentFileRevision());
				compareAction.selectionChanged((IStructuredSelection) treeViewer.getSelection());
			}
		});
		
		openAction = new OpenRevisionAction(CVSUIMessages.CVSHistoryPage_OpenAction, this);
		openAction.setEnabled(!treeViewer.getSelection().isEmpty());
		treeViewer.getTree().addSelectionListener(new SelectionAdapter(){
			public void widgetSelected(SelectionEvent e) {
				openAction.selectionChanged((IStructuredSelection) treeViewer.getSelection());
			}
		});
		
		// Add 'Open With...'  sub-menu
		openWithMenu = new OpenWithMenu(this);
		treeViewer.getTree().addSelectionListener(new SelectionAdapter(){
			public void widgetSelected(SelectionEvent e) {
				openWithMenu.selectionChanged((IStructuredSelection) treeViewer.getSelection());
			}
		});

		new OpenAndLinkWithEditorHelper(treeViewer) {
			protected void open(ISelection selection, boolean activate) {
				if (getSite() != null && selection instanceof IStructuredSelection) {
					IStructuredSelection structuredSelection= (IStructuredSelection)selection;
					if (compareMode){
						StructuredSelection sel = new StructuredSelection(new Object[] {getCurrentFileRevision(), structuredSelection.getFirstElement()});
						compareAction.selectionChanged(sel);
						compareAction.run();
					} else {
						//Pass in the entire structured selection to allow for multiple editor openings
						openAction.selectionChanged(structuredSelection);
						openAction.run();
					}
				}
			}

			protected void activate(ISelection selection) {
				int currentMode= OpenStrategy.getOpenMethod();
				try {
					OpenStrategy.setOpenMethod(OpenStrategy.DOUBLE_CLICK);
					open(selection, true);
				} finally {
					OpenStrategy.setOpenMethod(currentMode);
				}
			}

			protected void linkToEditor(ISelection selection) {
				// XXX: Not yet implemented, see http://bugs.eclipse.org/324185
			}
		};

		getContentsAction = getContextMenuAction(CVSUIMessages.HistoryView_getContentsAction, true /* needs progress */, new IWorkspaceRunnable() {
			public void run(IProgressMonitor monitor) throws CoreException {
				monitor.beginTask(null, 100);
				try {
					if(confirmOverwrite() && validateChange()) {
						IStorage currentStorage = currentSelection.getStorage(new SubProgressMonitor(monitor, 50));
						InputStream in = currentStorage.getContents();
						((IFile)file.getIResource()).setContents(in, false, true, new SubProgressMonitor(monitor, 50));
					}
				} catch (TeamException e) {
					throw new CoreException(e.getStatus());
				} finally {
					monitor.done();
				}
			}
		});
        PlatformUI.getWorkbench().getHelpSystem().setHelp(getContentsAction, IHelpContextIds.GET_FILE_CONTENTS_ACTION);

		getRevisionAction = getContextMenuAction(CVSUIMessages.HistoryView_getRevisionAction, true /* needs progress */, new IWorkspaceRunnable() {
			public void run(IProgressMonitor monitor) throws CoreException {
				ICVSRemoteFile remoteFile = (ICVSRemoteFile) CVSWorkspaceRoot.getRemoteResourceFor(((CVSFileRevision) currentSelection).getCVSRemoteFile());
				try {
					if(confirmOverwrite() && validateChange()) {
						CVSTag revisionTag = new CVSTag(remoteFile.getRevision(), CVSTag.VERSION);
						
						if(CVSAction.checkForMixingTags(getHistoryPageSite().getShell(), new IResource[] {file.getIResource()}, revisionTag)) {
							new UpdateOperation(
									null,
									new IResource[] {file.getIResource()},
									new Command.LocalOption[] {Update.IGNORE_LOCAL_CHANGES},
									revisionTag)
										.run(monitor);
							
							Display.getDefault().asyncExec(new Runnable() {
								public void run() {
									refresh();
								}
							});
						}
					}
				} catch (InvocationTargetException e) {
					throw CVSException.wrapException(e);
				} catch (InterruptedException e) {
					// Cancelled by user
				}
			}
		});
        PlatformUI.getWorkbench().getHelpSystem().setHelp(getRevisionAction, IHelpContextIds.GET_FILE_REVISION_ACTION);

		// Override MoveRemoteTagAction to work for log entries
		final IActionDelegate tagActionDelegate = new MoveRemoteTagAction() {
			protected ICVSResource[] getSelectedCVSResources() {
				ICVSResource[] resources = super.getSelectedCVSResources();
				if (resources == null || resources.length == 0) {
					ArrayList logEntrieFiles = null;
					IStructuredSelection selection = getSelection();
					if (!selection.isEmpty()) {
						logEntrieFiles = new ArrayList();
						Iterator elements = selection.iterator();
						while (elements.hasNext()) {
							Object next = elements.next();
							if (next instanceof CVSFileRevision) {
								logEntrieFiles.add(((CVSFileRevision)next).getCVSRemoteFile());
								continue;
							}
							if (next instanceof IAdaptable) {
								IAdaptable a = (IAdaptable) next;
								Object adapter = a.getAdapter(ICVSResource.class);
								if (adapter instanceof ICVSResource) {
									logEntrieFiles.add(((ILogEntry)adapter).getRemoteFile());
									continue;
								}
							}
						}
					}
					if (logEntrieFiles != null && !logEntrieFiles.isEmpty()) {
						return (ICVSResource[])logEntrieFiles.toArray(new ICVSResource[logEntrieFiles.size()]);
					}
				}
				return resources;
			}
            /*
             * Override the creation of the tag operation in order to support
             * the refresh of the view after the tag operation completes
             */
            protected ITagOperation createTagOperation() {
                return new TagInRepositoryOperation(getTargetPart(), getSelectedRemoteResources()) {
                    public void execute(IProgressMonitor monitor) throws CVSException, InterruptedException {
                        super.execute(monitor);
                        Display.getDefault().asyncExec(new Runnable() {
                            public void run() {
                                if( ! wasCancelled()) {
                                    refresh();
                                }
                            }
                        });
                    };
                };
            }
		};
		tagWithExistingAction = getContextMenuAction(CVSUIMessages.HistoryView_tagWithExistingAction, false /* no progress */, new IWorkspaceRunnable() {
			public void run(IProgressMonitor monitor) throws CoreException {
				tagActionDelegate.selectionChanged(tagWithExistingAction, treeViewer.getSelection());
				tagActionDelegate.run(tagWithExistingAction);
			}
		});
        PlatformUI.getWorkbench().getHelpSystem().setHelp(getRevisionAction, IHelpContextIds.TAG_WITH_EXISTING_ACTION);
        
		// Toggle text visible action
		toggleTextAction = new Action(TeamUIMessages.GenericHistoryView_ShowCommentViewer) {
			public void run() {
				setViewerVisibility();
				store.setValue(ICVSUIConstants.PREF_SHOW_COMMENTS, toggleTextAction.isChecked());
			}
		};
		toggleTextAction.setChecked(store.getBoolean(ICVSUIConstants.PREF_SHOW_COMMENTS));
		//PlatformUI.getWorkbench().getHelpSystem().setHelp(toggleTextAction, IHelpContextIds.SHOW_COMMENT_IN_HISTORY_ACTION);

		// Toggle wrap comments action
		toggleTextWrapAction = new Action(TeamUIMessages.GenericHistoryView_WrapComments) {
			public void run() {
				setViewerVisibility();
				store.setValue(ICVSUIConstants.PREF_WRAP_COMMENTS, toggleTextWrapAction.isChecked());
			}
		};
		toggleTextWrapAction.setChecked(store.getBoolean(ICVSUIConstants.PREF_WRAP_COMMENTS));
		//PlatformUI.getWorkbench().getHelpSystem().setHelp(toggleTextWrapAction, IHelpContextIds.SHOW_TAGS_IN_HISTORY_ACTION);

		// Toggle list visible action
		toggleListAction = new Action(TeamUIMessages.GenericHistoryView_ShowTagViewer) {
			public void run() {
				setViewerVisibility();
				store.setValue(ICVSUIConstants.PREF_SHOW_TAGS, toggleListAction.isChecked());
			}
		};
		toggleListAction.setChecked(store.getBoolean(ICVSUIConstants.PREF_SHOW_TAGS));
		//PlatformUI.getWorkbench().getHelpSystem().setHelp(toggleListAction, IHelpContextIds.SHOW_TAGS_IN_HISTORY_ACTION);

		//Toggle search field
		toggleSearchAction= new Action(CVSUIMessages.CVSHistoryPage_ShowSearchField) {
			public void run() {
				setViewerVisibility();
				store.setValue(ICVSUIConstants.PREF_SHOW_SEARCH, toggleSearchAction.isChecked());
				if (!toggleSearchAction.isChecked()){
					if (searchFilter != null)
					  treeViewer.removeFilter(searchFilter);
				} else {
					searchField.setMessage(CVSUIMessages.CVSHistoryPage_EnterSearchTerm);
					searchField.selectAll();
					searchField.setFocus();
				}
			}
		};
		toggleSearchAction.setChecked(store.getBoolean(ICVSUIConstants.PREF_SHOW_SEARCH));
		//PlatformUI.getWorkbench().getHelpSystem().setHelp(toggleListAction, IHelpContextIds.SHOW_TAGS_IN_HISTORY_ACTION);
		
		toggleFilterAction = new Action(CVSUIMessages.CVSHistoryPage_NoFilter){
			public void run(){
				if (historyFilter != null)
					treeViewer.removeFilter(historyFilter);
					historyFilter = null;
					String old = CVSHistoryPage.this.description;
					CVSHistoryPage.this.description = null;
					CVSHistoryPage.this.firePropertyChange(CVSHistoryPage.this, P_NAME, old, getName());
					toggleFilterAction.setEnabled(false);
			}
		};
		toggleFilterAction.setEnabled(historyFilter != null);
		
		//Create the filter action
		cvsHistoryFilter = new CVSHistoryFilterAction(this);
		cvsHistoryFilter.setText(CVSUIMessages.CVSHistoryPage_FilterOn);
		cvsHistoryFilter.init(treeViewer);
		cvsHistoryFilter.setToolTipText(CVSUIMessages.CVSHistoryPage_FilterHistoryTooltip);
		cvsHistoryFilter.setImageDescriptor(CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_FILTER_HISTORY));
		
		//Contribute actions to popup menu
		MenuManager menuMgr = new MenuManager();
		Menu menu = menuMgr.createContextMenu(treeViewer.getTree());
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager menuMgr) {
				fillTableMenu(menuMgr);
			}
		});
		menuMgr.setRemoveAllWhenShown(true);
		treeViewer.getTree().setMenu(menu);
		//Don't add the object contribution menu items if this page is hosted in a dialog
		IHistoryPageSite parentSite = getHistoryPageSite();
		if (!parentSite.isModal()) {
			IWorkbenchPart part = parentSite.getPart();
			if (part != null) {
				IWorkbenchPartSite workbenchPartSite = part.getSite();
				workbenchPartSite.registerContextMenu(menuMgr, treeViewer);
			}
			IPageSite pageSite = parentSite.getWorkbenchPageSite();
			if (pageSite != null) {
				IActionBars actionBars = pageSite.getActionBars();
				// Contribute toggle text visible to the toolbar drop-down
				IMenuManager actionBarsMenu = actionBars.getMenuManager();
				if (actionBarsMenu != null){
					actionBarsMenu.add(toggleTextWrapAction);
					actionBarsMenu.add(new Separator());
					actionBarsMenu.add(toggleTextAction);
					actionBarsMenu.add(toggleListAction);
					actionBarsMenu.add(new Separator());
					actionBarsMenu.add(toggleSearchAction);
					actionBarsMenu.add(new Separator());
					actionBarsMenu.add(cvsHistoryFilter);
					actionBarsMenu.add(toggleFilterAction);
				}
				// Create actions for the text editor
				copyAction = new TextViewerAction(textViewer, ITextOperationTarget.COPY);
				copyAction.setText(CVSUIMessages.HistoryView_copy);
				actionBars.setGlobalActionHandler(ITextEditorActionConstants.COPY, copyAction);
				
				selectAllAction = new TextViewerAction(textViewer, ITextOperationTarget.SELECT_ALL);
				selectAllAction.setText(CVSUIMessages.HistoryView_selectAll);
				actionBars.setGlobalActionHandler(ITextEditorActionConstants.SELECT_ALL, selectAllAction);
				
				copyTagAction = new TableViewerAction(tagViewer);
				copyTagAction.setText(CVSUIMessages.HistoryView_copy);
				copyTagAction.setEnabled(false);
				
				actionBars.updateActionBars();
			}
		}
		
		
		
		//Create the local tool bar
		IToolBarManager tbm = parentSite.getToolBarManager();
		if (tbm != null) {
			String fileNameQualifier = getFileNameQualifier();
			//Add groups
			tbm.add(new Separator(fileNameQualifier + "grouping"));	//$NON-NLS-1$
			tbm.appendToGroup(fileNameQualifier+"grouping", groupByDateMode); //$NON-NLS-1$
			tbm.add(new Separator(fileNameQualifier+"modes"));	//$NON-NLS-1$
			tbm.appendToGroup(fileNameQualifier+"modes", remoteLocalMode); //$NON-NLS-1$
			tbm.appendToGroup(fileNameQualifier+"modes", localMode); //$NON-NLS-1$
			tbm.appendToGroup(fileNameQualifier+"modes", remoteMode); //$NON-NLS-1$
			tbm.add(new Separator(fileNameQualifier+"collapse")); //$NON-NLS-1$
			tbm.appendToGroup(fileNameQualifier+"collapse", collapseAll); //$NON-NLS-1$
			if (!parentSite.isModal()) {
				//don't bother adding the compare mode toolbar button if in
				//a dialog; you can only compare from dialogs
				tbm.appendToGroup(fileNameQualifier+"collapse", compareModeAction);  //$NON-NLS-1$
			}
			tbm.update(false);
		}

		menuMgr = new MenuManager();
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager menuMgr) {
				fillTextMenu(menuMgr);
			}
		});
		StyledText text = textViewer.getTextWidget();
		menu = menuMgr.createContextMenu(text);
		text.setMenu(menu);
		
		menuMgr = new MenuManager();
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager menuMgr) {
				fillTagMenu(menuMgr);
			}
		});
		menu = menuMgr.createContextMenu(tagViewer.getControl());
		tagViewer.getControl().setMenu(menu);
	}

	private String getFileNameQualifier() {
		//Just append the current system time to generate a unique group name
		return Long.toString(System.currentTimeMillis());
	}

	private boolean isLocalHistoryFilteredOut() {
		return localFilteredOut;
	}
	
	private boolean isRemoteHistoryFilteredOut(){
		return remoteFilteredOut;
	}
	
	/* private */ void fillTableMenu(IMenuManager manager) {
		// file actions go first (view file)
		IHistoryPageSite parentSite = getHistoryPageSite();
		manager.add(new Separator(IWorkbenchActionConstants.GROUP_FILE));
		
		if (file != null && !parentSite.isModal()){
			manager.add(openAction);
			
			MenuManager openWithSubmenu = new MenuManager(
					CVSUIMessages.CVSHistoryPage_OpenWithMenu);
			openWithSubmenu.add(openWithMenu);
			manager.add(openWithSubmenu);
			
			manager.add(compareAction);
			manager.add(new Separator("openCompare")); //$NON-NLS-1$
		}
		if (file != null &&
		  !(file instanceof RemoteFile)) {
			// Add the "Add to Workspace" action if 1 revision is selected.
			ISelection sel = treeViewer.getSelection();
			if (!sel.isEmpty()) {
				if (sel instanceof IStructuredSelection) {
					IStructuredSelection tempSelection = (IStructuredSelection) sel;
					if (tempSelection.size() == 1) {
						manager.add(getContentsAction);
						if (!(tempSelection.getFirstElement() instanceof LocalFileRevision)) {
							manager.add(getRevisionAction);
							manager.add(new Separator());
							if (!parentSite.isModal())
								manager.add(tagWithExistingAction);
						}
					}
				}
			}
		}
		
		if (!parentSite.isModal()){
			manager.add(new Separator("additions")); //$NON-NLS-1$
			manager.add(refreshAction);
			manager.add(new Separator("additions-end")); //$NON-NLS-1$
		}
	}

	private void fillTextMenu(IMenuManager manager) {
		manager.add(copyAction);
		manager.add(selectAllAction);
	}
	
	private void fillTagMenu(IMenuManager manager) {
		manager.add(copyTagAction);
		manager.add(new Separator());
		manager.add(new SortTagsAction(true));
		manager.add(new SortTagsAction(false));
	}

	/**
	 * Creates the group that displays lists of the available repositories and
	 * team streams.
	 * 
	 * @param the
	 *            parent composite to contain the group
	 * @return the group control
	 */
	protected TreeViewer createTree(Composite parent) {

		historyTableProvider = new CVSHistoryTableProvider();
		TreeViewer viewer = historyTableProvider.createTree(parent);

		viewer.setContentProvider(new ITreeContentProvider() {
			public Object[] getElements(Object inputElement) {

				// The entries of already been fetch so return them
				if (entries != null)
					return entries;
				
				if (!(inputElement instanceof IFileHistory) &&
					!(inputElement instanceof AbstractHistoryCategory[]))
					return new Object[0];

				if (inputElement instanceof AbstractHistoryCategory[]){
					return (AbstractHistoryCategory[]) inputElement;
				}
				
				final IFileHistory fileHistory = (IFileHistory) inputElement;
				entries = fileHistory.getFileRevisions();
				
				return entries;
			}

			public void dispose() {
			}

			public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
				entries = null;
			}

			public Object[] getChildren(Object parentElement) {
				if (parentElement instanceof AbstractHistoryCategory){
					return ((AbstractHistoryCategory) parentElement).getRevisions();
				}
				
				return null;
			}

			public Object getParent(Object element) {
				return null;
			}

			public boolean hasChildren(Object element) {
				if (element instanceof AbstractHistoryCategory){
					IFileRevision[] revs = ((AbstractHistoryCategory) element).getRevisions();
					if (revs != null)
						return revs.length > 0;
				}
				return false;
			}
		});

		viewer.addSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				ISelection selection = event.getSelection();
				if (selection == null || !(selection instanceof IStructuredSelection)) {
					textViewer.setDocument(new Document("")); //$NON-NLS-1$
					tagViewer.setInput(null);
					setStatusLineMessage(null);
					return;
				}
				IStructuredSelection ss = (IStructuredSelection)selection;
				if (ss.size() != 1) {
					textViewer.setDocument(new Document("")); //$NON-NLS-1$
					tagViewer.setInput(null);
					setStatusLineMessage(null);
					return;
				}
				Object o = ss.getFirstElement();
				if (o instanceof AbstractHistoryCategory){
					textViewer.setDocument(new Document("")); //$NON-NLS-1$
					tagViewer.setInput(null);
					setStatusLineMessage(null);
					return;
				}
				IFileRevision entry = (IFileRevision)o;
				textViewer.setDocument(new Document(entry.getComment()));
				tagViewer.setInput(entry.getTags());
				setStatusLineMessage(CVSHistoryTableProvider.getCommentAsSingleLine(entry));
			}
		});

		return viewer;
	}

	private Action getContextMenuAction(String title, final boolean needsProgressDialog, final IWorkspaceRunnable action) {
		return new Action(title) {
			public void run() {
				try {
					if (file == null) return;
					ISelection selection = treeViewer.getSelection();
					if (!(selection instanceof IStructuredSelection)) return;
					IStructuredSelection ss = (IStructuredSelection)selection;
					Object o = ss.getFirstElement();
					
					if (o instanceof AbstractHistoryCategory)
						return;
					
					currentSelection = (IFileRevision)o;
					if(needsProgressDialog) {
						PlatformUI.getWorkbench().getProgressService().run(true, true, new IRunnableWithProgress() {
							public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
								try {
									action.run(monitor);
								} catch (CoreException e) {
									throw new InvocationTargetException(e);
								}
							}
						});
					} else {
						try {
							action.run(null);
						} catch (CoreException e) {
							throw new InvocationTargetException(e);
						}
					}
				} catch (InvocationTargetException e) {
					IHistoryPageSite parentSite = getHistoryPageSite();
					CVSUIPlugin.openError(parentSite.getShell(), null, null, e, CVSUIPlugin.LOG_NONTEAM_EXCEPTIONS);
				} catch (InterruptedException e) {
					// Do nothing
				}
			}
			
			public boolean isEnabled() {
				ISelection selection = treeViewer.getSelection();
				if (!(selection instanceof IStructuredSelection)) return false;
				IStructuredSelection ss = (IStructuredSelection)selection;
				if(ss.size() != 1) return false;
				return true;
			}
		};
	}

	private boolean confirmOverwrite() {
		if (file!=null && file.getIResource().exists()) {
			try {
				if(file.isModified(null)) {
					String title = CVSUIMessages.HistoryView_overwriteTitle;
					String msg = CVSUIMessages.HistoryView_overwriteMsg;
					IHistoryPageSite parentSite = getHistoryPageSite();
					final MessageDialog dialog = new MessageDialog(parentSite.getShell(), title, null, msg, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.CANCEL_LABEL }, 0);
					final int[] result = new int[1];
					parentSite.getShell().getDisplay().syncExec(new Runnable() {
					public void run() {
						result[0] = dialog.open();
					}});
					if (result[0] != 0) {
						// cancel
						return false;
					}
				}
			} catch(CVSException e) {
				CVSUIPlugin.log(e);
			}
		}
		return true;
	}
	
	private boolean validateChange(){
		if (file!=null && file.getIResource().exists()) {
			IResourceChangeDescriptionFactory factory = ResourceChangeValidator.getValidator().createDeltaFactory();
			factory.change((IFile) file.getIResource());
			return IDE.promptToConfirm(getHistoryPageSite().getShell(), CVSUIMessages.CVSHistoryPage_ValidateChangeTitle, NLS.bind(CVSUIMessages.CVSHistoryPage_ValidateChangeMessage, new String[]{file.getName()}), factory.getDelta(), new String[0], true /* syncExec */);
		}
		
		return false;
	}

	/*
	 * Refresh the view by refetching the log entries for the remote file
	 */
	public void refresh() {
		refresh(CVSFileHistory.REFRESH_LOCAL | CVSFileHistory.REFRESH_REMOTE);
	}
	
	public void refresh(int refreshFlags) {
		printDebugInfo("CVSHistoryPage#refresh", (IFile)(previousFile != null ? previousFile.getIResource() : null), cvsFileHistory, new Throwable()); //$NON-NLS-1$
		//refetch revisions, not a select only job
		// TODO
		refreshHistory(true, false, refreshFlags);
	}

	private void refreshHistory(boolean refetch, boolean selectOnly, int refreshFlags) {
		if (refreshCVSFileHistoryJob.getState() != Job.NONE){
			RefreshCVSFileHistory oldJob = refreshCVSFileHistoryJob;
			oldJob.cancel();
			refreshCVSFileHistoryJob = new RefreshCVSFileHistory(this);
			refreshCVSFileHistoryJob.setLocalFileRevision(oldJob.localFileRevision);
			refreshCVSFileHistoryJob.setSelectLocal(oldJob.useLocalSelect);
			refetch = true;
			selectOnly = false;
			refreshFlags = CVSFileHistory.REFRESH_ALL;
			printDebugInfo("CVSHistoryPage#refreshHistory, cancel old job", (IFile)(previousFile != null ? previousFile.getIResource() : null), cvsFileHistory, null); //$NON-NLS-1$
		}
		refreshCVSFileHistoryJob.setFileHistory(cvsFileHistory);
		IResource resource = previousFile.getIResource();
		if (resource != null){
			IResource workspaceFile = ResourcesPlugin.getWorkspace().getRoot().findMember(resource.getFullPath());
			refreshCVSFileHistoryJob.setWorkspaceFile((IFile) workspaceFile);
		}
		//if we need to refetch it's not a select only job and vice versa
		refreshCVSFileHistoryJob.setSelectOnly(selectOnly);
		refreshCVSFileHistoryJob.setRefetchHistory(refetch);
		refreshCVSFileHistoryJob.setIncludeLocals(!isLocalHistoryFilteredOut());
		refreshCVSFileHistoryJob.setIncludeRemote(!isRemoteHistoryFilteredOut());
		refreshCVSFileHistoryJob.setGrouping(groupingOn);
		refreshCVSFileHistoryJob.setRefreshFlags(refreshFlags);
		IHistoryPageSite parentSite = getHistoryPageSite();
		printDebugInfo("CVSHistoryPage#refreshHistory, about to schedule RefreshCVSFileHistoryJob", (IFile)resource, cvsFileHistory, null); //$NON-NLS-1$
		Utils.schedule(refreshCVSFileHistoryJob, getWorkbenchSite(parentSite));
	}

	private IWorkbenchPartSite getWorkbenchSite(IHistoryPageSite parentSite) {
		IWorkbenchPart part = parentSite.getPart();
		if (part != null)
			return part.getSite();
		return null;
	}

	/**
	 * Select the revision in the receiver.
	 */
	public void selectRevision(String revision) {
		IFileRevision entry = null;
		entry = getFileRevision(revision);
	
		if (entry != null) {
			IStructuredSelection selection = new StructuredSelection(entry);
			treeViewer.getTree().setRedraw(false);
			treeViewer.setSelection(selection, true);
			treeViewer.getTree().setRedraw(true);
		} else {
			//nothing to select so clear selection
			treeViewer.getTree().deselectAll();
		}
	}
	
	private IFileRevision getFileRevision(String revision) {
		if (entries != null) {
			for (int i = 0; i < entries.length; i++) {
				if (entries[i].getContentIdentifier().equals(revision)) {
					return entries[i];
				}
			}
		} else if (cvsFileHistory != null) {
			return cvsFileHistory.getFileRevision(revision);
		}
		return null;
	}
	
	/**
	 * Select the local revision in the receiver. Local revisions are differentiated by their
	 * timestamps.
	 */
	public void selectLocalRevision(long timeStamp){
		IFileRevision entry = null;
		if (entries != null) {
			for (int i = 0; i < entries.length; i++) {
				if (entries[i].getTimestamp() == timeStamp) {
					entry = entries[i];
					break;
				}
			}
		}else if (cvsFileHistory != null) {
			IFileRevision[] tempEntries = cvsFileHistory.getFileRevisions();
			for (int i = 0; i < tempEntries.length; i++) {
				if (tempEntries[i].getTimestamp() == timeStamp) {
					entry = tempEntries[i];
					break;
				}
			}
		}
	
		if (entry != null) {
			IStructuredSelection selection = new StructuredSelection(entry);
			treeViewer.getTree().setRedraw(false);
			treeViewer.setSelection(selection, true);
			treeViewer.getTree().setRedraw(true);
		} else {
			//nothing to select so clear selection
			treeViewer.getTree().deselectAll();
		}
	}
	
	protected static ICVSFile getCVSFile(Object object) {
		// First, adapt to IResource and ensure mapped to CVS
		IResource resource = (IResource)Adapters.adapt(object, IResource.class);
		if (resource instanceof IFile) {
			RepositoryProvider provider = RepositoryProvider.getProvider(resource.getProject());
			if (provider instanceof CVSTeamProvider)
				return CVSWorkspaceRoot.getCVSFileFor((IFile) resource);
			return null;
		}
		// Second, try ICVSFile
		ICVSFile remoteFile = (ICVSFile)Adapters.adapt(object, ICVSFile.class);
		if (remoteFile != null) {
			return remoteFile;
		}
		// Next, try ICVSResource
		ICVSResource remote = (ICVSResource)Adapters.adapt(object, ICVSResource.class);
		if (remote instanceof RemoteFile) {
			return (ICVSFile)remote;
		}
		// Next, try IResourceVariant
		IResourceVariant variant = (IResourceVariant)Adapters.adapt(object, IResourceVariant.class);
		if (variant instanceof RemoteFile) {
			return (ICVSFile)remote;
		}
		// Finally, try IFileRevision
		IFileRevision revision = (IFileRevision)Adapters.adapt(object, IFileRevision.class);
		if (revision instanceof CVSFileRevision) {
			return ((CVSFileRevision)revision).getCVSRemoteFile();
		}
		
		return null;
	}

	/* private */void setViewerVisibility() {
		boolean showText = toggleTextAction.isChecked();
		boolean showList = toggleListAction.isChecked();
		boolean showSearch = toggleSearchAction.isChecked();
		
		//check to see if this page is being shown in a dialog, in which case
		//don't show the text and list panes
		IHistoryPageSite parentSite = getHistoryPageSite();
		if (parentSite.isModal()){
			showText = false;
			showList = false;
		}

		
		if (showText && showList && showSearch) {
			//tree + tag + text + search
			tagAndTextComposite.setVisible(true);
			searchComposite.setVisible(true);
			sashForm.setWeights(new int[] {60, 25, 15});
			sashForm.setMaximizedControl(null);
			innerSashForm.setMaximizedControl(null);
			searchSashForm.setMaximizedControl(null);
		} else if (showText && showSearch) {
			//tree + text + search
			tagAndTextComposite.setVisible(true);
			searchComposite.setVisible(true);
			sashForm.setWeights(new int[] {60, 25, 15});
			sashForm.setMaximizedControl(null);
			innerSashForm.setMaximizedControl(textViewer.getTextWidget());
			searchSashForm.setMaximizedControl(searchField);
		} else if (showList && showSearch) {
			//tree + tag + search
			tagAndTextComposite.setVisible(true);
			searchComposite.setVisible(true);
			sashForm.setWeights(new int[] {60, 25, 15});
			sashForm.setMaximizedControl(null);
			innerSashForm.setMaximizedControl(tagViewer.getTable());
			searchSashForm.setMaximizedControl(searchField);
		} else if (showSearch){
			//tree + search
			tagAndTextComposite.setVisible(false);
			searchComposite.setVisible(true);
			sashForm.setWeights(new int[] {85, 0, 15});
			sashForm.setMaximizedControl(null);
			innerSashForm.setMaximizedControl(null);
			searchSashForm.setMaximizedControl(searchField);
		} else if (showText && showList) {
			//tree + tag + text
			tagAndTextComposite.setVisible(true);
			searchComposite.setVisible(false);
			sashForm.setWeights(new int[] {70, 30, 0});
			sashForm.setMaximizedControl(null);
			innerSashForm.setMaximizedControl(null);
			searchSashForm.setMaximizedControl(searchField);
		} else if (showText) {
			//tree + text
			tagAndTextComposite.setVisible(true);
			searchComposite.setVisible(false);
			sashForm.setWeights(new int[] {70, 30, 0});
			sashForm.setMaximizedControl(null);
			innerSashForm.setMaximizedControl(textViewer.getTextWidget());
		} else if (showList) {
			//tree + tag
			tagAndTextComposite.setVisible(true);
			searchComposite.setVisible(false);
			sashForm.setWeights(new int[] {70, 30, 0});
			sashForm.setMaximizedControl(null);
			innerSashForm.setMaximizedControl(tagViewer.getTable());
		} else {
			//tree
			tagAndTextComposite.setVisible(false);
			searchComposite.setVisible(false);
			sashForm.setMaximizedControl(treeViewer.getControl());
		}

		boolean wrapText = toggleTextWrapAction.isChecked();
		textViewer.getTextWidget().setWordWrap(wrapText);
	}

	private void initializeImages() {
		CVSUIPlugin plugin = CVSUIPlugin.getPlugin();
		versionImage = plugin.getImageDescriptor(ICVSUIConstants.IMG_PROJECT_VERSION).createImage();
		branchImage = plugin.getImageDescriptor(ICVSUIConstants.IMG_TAG).createImage();
	}
	
	public void dispose() {
		shutdown = true;
		
		
		if (!sashForm.isDisposed() && !innerSashForm.isDisposed()) {
			saveState(); // called when switching pages
			if (disposeListener != null){
				sashForm.getParent().removeDisposeListener(disposeListener);
				disposeListener = null;
			}
		}

		if (resourceListener != null){
			ResourcesPlugin.getWorkspace().removeResourceChangeListener(resourceListener);
			resourceListener = null;
		}
		
		if (branchImage != null) {
			branchImage.dispose();
			branchImage = null;
		}
		if (versionImage != null) {
			versionImage.dispose();
			versionImage = null;
		}
		if (rulerSelectionListener != null) {
			rulerSelectionListener.dispose();
			rulerSelectionListener= null;
		}
		
		//Cancel any incoming
		if (refreshCVSFileHistoryJob != null) {
			if (refreshCVSFileHistoryJob.getState() != Job.NONE) {
				refreshCVSFileHistoryJob.cancel();
			}
		}

		super.dispose();
	}

	public IFileRevision getCurrentFileRevision() {
		if (currentFileRevision != null)
			return currentFileRevision;

		if (file != null) {
			try {
				//Case 1 : file is remote
				if (file instanceof RemoteFile) {
					RemoteFile remote = (RemoteFile) file;
					currentFileRevision = cvsFileHistory.getFileRevision(remote.getContentIdentifier());
					//remote.getContents(monitor);
					//currentFileRevision = new CVSFileRevision(remote.getLogEntry(monitor));
					return currentFileRevision;
				}
				//Case 2 : file is local
				//if (file.isModified(monitor)) {
				//file has been modified locally
				IFile localFile = (IFile) file.getIResource();
				if (localFile != null) {
					//make sure that there's actually a resource associated with the file
					currentFileRevision = new LocalFileRevision(localFile);
				} else {
					//no local version exists
					if (file.getSyncInfo() != null) {
						currentFileRevision = cvsFileHistory.getFileRevision(file.getSyncInfo().getRevision());
					}
				}
				return currentFileRevision;
			} catch (CVSException e) {
			}
		}

		return null;
	}
	
	private final class CVSRevisionAnnotationController extends
			RevisionAnnotationController {
		public CVSRevisionAnnotationController(IWorkbenchPage page, IFile file) {
			super(page, file, treeViewer);
		}

		public CVSRevisionAnnotationController(IWorkbenchPage page, IStorageEditorInput editorInput) {
			super(page, editorInput, treeViewer);
		}

		protected Object getHistoryEntry(Revision selected) {
			return CVSHistoryPage.this.getFileRevision(selected.getId());
		}
	}


	private final class SearchHistoryTable implements Runnable {
		public void run() {
			String searchString = searchField.getText();
			if (searchString.equals("") || //$NON-NLS-1$
				searchString.equals(CVSUIMessages.CVSHistoryPage_EnterSearchTerm)) {
				 if (searchFilter != null)
					 treeViewer.removeFilter(searchFilter);
				return;
			}
			

			if (searchFilter != null)
				treeViewer.removeFilter(searchFilter);

			searchFilter = new CVSHistorySearchFilter(searchString);

			if (historyFilter != null)
				treeViewer.removeFilter(historyFilter);

			treeViewer.addFilter(searchFilter);
		}
	}


	private class RefreshCVSFileHistory extends Job {
		private final static int NUMBER_OF_CATEGORIES = 4;
		
		private CVSFileHistory fileHistory;
		private AbstractHistoryCategory[] categories;
		private boolean grouping;
		private Object[] elementsToExpand;
		private boolean revisionsFound;
		private IFile workspaceFile;
		private CVSHistoryPage page;
		private boolean selectOnly;
		private boolean useLocalSelect;
		
		private CVSLocalFileRevision localFileRevision;

		private int refreshFlags = CVSFileHistory.REFRESH_LOCAL | CVSFileHistory.REFRESH_REMOTE;
		
		public RefreshCVSFileHistory(CVSHistoryPage page) {
			super(CVSUIMessages.HistoryView_fetchHistoryJob);
			this.page = page;
		}
		
		public void setWorkspaceFile(IFile workspaceFile) {
			this.workspaceFile = workspaceFile;
		}

		public void setIncludeLocals(boolean flag) {
			if (fileHistory != null)
				fileHistory.includeLocalRevisions(flag);
		}
		
		public void setIncludeRemote(boolean flag){
			if (fileHistory != null)
				fileHistory.includeRemoteRevisions(flag);
		}

		public void setRefetchHistory(boolean refetch) {
			if (fileHistory != null)
				fileHistory.setRefetchRevisions(refetch);
		}

		public void setFileHistory(CVSFileHistory fileHistory) {
			this.fileHistory = fileHistory;
		}
	
		public void setGrouping (boolean value){
			this.grouping = value;
		}
		
		public void setSelectOnly(boolean select) {
			this.selectOnly = select;
		}

		public void setSelectLocal(boolean localSelect) {
			this.useLocalSelect = localSelect;
		}

		public void setLocalFileRevision(CVSLocalFileRevision localRev){
			this.localFileRevision = localRev;
		}
		
		public IStatus run(IProgressMonitor monitor)  {
			final int cachedRefreshFlags = refreshFlags;
			final boolean cachedSelectOnly= selectOnly;
			IStatus status = Status.OK_STATUS;
			printDebugInfo("RefreshCVSFileHistory#run started for", workspaceFile, fileHistory, null); //$NON-NLS-1$
			if (fileHistory != null && !shutdown) {
				printDebugInfo("RefreshCVSFileHistory#run checkpoint 1", workspaceFile, fileHistory, null); //$NON-NLS-1$

				//If fileHistory terminates in a bad way, try to fetch the local
				//revisions only
				boolean localFetched = false;
				boolean needsUpdate = true;
				if (!fileHistory.isInitialized()
						&& fileHistory.isIncludeLocal()
						&& (cachedRefreshFlags & CVSFileHistory.REFRESH_REMOTE) > 0) {
					// If this is the first refresh, show the local history before hitting the server
					try {
						printDebugInfo("RefreshCVSFileHistory#run checkpoint 2", workspaceFile, fileHistory, null); //$NON-NLS-1$
						fileHistory.refresh(CVSFileHistory.REFRESH_LOCAL, monitor);
						updateTable(cachedSelectOnly);
						localFetched = true;
						needsUpdate = false;
					} catch (TeamException e) {
						// Ignore and try the full refresh
						printDebugInfo("RefreshCVSFileHistory#run encountered an exception(1)", workspaceFile, fileHistory, e); //$NON-NLS-1$
					}
				}
				try {
					printDebugInfo("RefreshCVSFileHistory#run checkpoint 3", workspaceFile, fileHistory, null); //$NON-NLS-1$
					fileHistory.refresh(cachedRefreshFlags, monitor);
					needsUpdate = true;
				} catch (OperationCanceledException ex) {
					printDebugInfo("RefreshCVSFileHistory#run OperationCanceledException", workspaceFile, fileHistory, ex); //$NON-NLS-1$
					throw ex;
				} catch (TeamException ex) {
					printDebugInfo("RefreshCVSFileHistory#run encountered an exception(2)", workspaceFile, fileHistory, ex); //$NON-NLS-1$
					if (!localFetched) {
						try {
							fileHistory.refresh(CVSFileHistory.REFRESH_LOCAL, monitor);
							needsUpdate = true;
						} catch (TeamException e) {
							// Ignore and allow the original exception to go through
							printDebugInfo("RefreshCVSFileHistory#run encountered an exception(3)", workspaceFile, fileHistory, e); //$NON-NLS-1$
						}
					}
					status = new CVSStatus(ex.getStatus().getSeverity(), ex.getStatus().getCode(), ex.getMessage(), ex);
				}
				if (needsUpdate) {
					printDebugInfo("RefreshCVSFileHistory#run checkpoint 4", workspaceFile, fileHistory, null); //$NON-NLS-1$
					updateTable(cachedSelectOnly);
				}
			}

			if (status != Status.OK_STATUS ) {
				this.setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE);
				this.setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE);
			}
			printDebugInfo("RefreshCVSFileHistory#run finished, status: " + status, workspaceFile, fileHistory, null); //$NON-NLS-1$
			return status;
		}

		private void updateTable(final boolean selectOnly) {
			if (grouping)
				revisionsFound = sortRevisions();
			
			Utils.asyncExec(new Runnable() {
				public void run() {
					printDebugInfo("RefreshCVSFileHistory#updateTable, in asyncExec", workspaceFile, cvsFileHistory, null); //$NON-NLS-1$
					treeViewer.refresh();
					historyTableProvider.setFile(fileHistory, workspaceFile);
					//historyTableProvider.setWorkspaceFile(workspaceFile);
					if (!selectOnly){
						if (grouping) {
							mapExpandedElements(treeViewer.getExpandedElements());
							treeViewer.getTree().setLinesVisible(revisionsFound);
							treeViewer.getTree().setRedraw(false);
							printDebugInfo("RefreshCVSFileHistory#updateTable, setInput:grouping", workspaceFile, cvsFileHistory, null); //$NON-NLS-1$
							treeViewer.setInput(categories);
							//if user is switching modes and already has expanded elements
							//selected try to expand those, else expand all
							if (elementsToExpand.length > 0)
								treeViewer.setExpandedElements(elementsToExpand);
							else {
								treeViewer.expandAll();
								Object[] el = treeViewer.getExpandedElements();
								if (el != null && el.length > 0) {
									treeViewer.setSelection(new StructuredSelection(el[0]));
									treeViewer.getTree().deselectAll();
								}
							}
							treeViewer.getTree().setRedraw(true);
						} else {
							if (fileHistory.getFileRevisions().length > 0) {
								treeViewer.getTree().setLinesVisible(true);
								printDebugInfo("RefreshCVSFileHistory#updateTable, setInput:no grouping", workspaceFile, cvsFileHistory, null); //$NON-NLS-1$
								treeViewer.setInput(fileHistory);
							} else {
								categories = new AbstractHistoryCategory[] {getErrorMessage()};
								treeViewer.getTree().setLinesVisible(false);
								treeViewer.setInput(categories);
							}
						}
					}
					//Update the history (if it exists) to reflect the new
					//counts
					if (historyFilter != null){
						CVSHistoryFilter tempFilter = new CVSHistoryFilter(historyFilter.branchName, historyFilter.author, historyFilter.comment, historyFilter.fromDate, historyFilter.toDate, historyFilter.isOr);
						showFilter(tempFilter);
					}
					
					//Select the current file if we didn't have to refetch the history
					if (file != null){
						try {
							if (useLocalSelect){
								page.selectLocalRevision(localFileRevision.getTimestamp());
							} else {
								byte[] syncBytes = file.getSyncBytes();
								if (syncBytes != null) {
									String workspaceRevision = ResourceSyncInfo.getRevision(syncBytes);
									page.selectRevision(workspaceRevision);
								}
							}
						} catch (CVSException e){
						}
					}
				}
			}, treeViewer);
		}

		private void mapExpandedElements(Object[] expandedElements) {
			//store the names of the currently expanded categories in a map
			HashMap elementMap = new HashMap();
			for (int i=0; i<expandedElements.length; i++){
				elementMap.put(((DateHistoryCategory)expandedElements[i]).getName(), null);
			}
			
			//Go through the new categories and keep track of the previously expanded ones
			ArrayList expandable = new ArrayList();
			for (int i = 0; i<categories.length; i++){
				//check to see if this category is currently expanded
				if (elementMap.containsKey(categories[i].getName())){
					expandable.add(categories[i]);
				}
			}
			
			elementsToExpand = new Object[expandable.size()];
			elementsToExpand = expandable.toArray(new Object[expandable.size()]);
		}

		private boolean sortRevisions() {
			IFileRevision[] fileRevision = fileHistory.getFileRevisions();
			
			//Create the 4 categories
			DateHistoryCategory[] tempCategories = new DateHistoryCategory[NUMBER_OF_CATEGORIES];
			//Get a calendar instance initialized to the current time
			Calendar currentCal = Calendar.getInstance();
			tempCategories[0] = new DateHistoryCategory(CVSUIMessages.CVSHistoryPage_Today, currentCal, null);
			//Get yesterday
			Calendar yesterdayCal = Calendar.getInstance();
			yesterdayCal.roll(Calendar.DAY_OF_YEAR, -1);
			tempCategories[1] = new DateHistoryCategory(CVSUIMessages.CVSHistoryPage_Yesterday, yesterdayCal, null);
			//Get this month
			Calendar monthCal = Calendar.getInstance();
			monthCal.set(Calendar.DAY_OF_MONTH, 1);
			tempCategories[2] = new DateHistoryCategory(CVSUIMessages.CVSHistoryPage_ThisMonth, monthCal, yesterdayCal);
			//Everything before this month is previous
			tempCategories[3] = new DateHistoryCategory(CVSUIMessages.CVSHistoryPage_Previous, null, monthCal);
		
			ArrayList finalCategories = new ArrayList();
			for (int i = 0; i<NUMBER_OF_CATEGORIES; i++){
				tempCategories[i].collectFileRevisions(fileRevision, false);
				if (tempCategories[i].hasRevisions())
					finalCategories.add(tempCategories[i]);
			}
			
			//Assume that some revisions have been found
			boolean revisionsFound = true;
			
			if (finalCategories.size() == 0){
				//no revisions found for the current mode, so add a message category
				finalCategories.add(getErrorMessage());
				revisionsFound = false;
			}
			
			categories = (AbstractHistoryCategory[])finalCategories.toArray(new AbstractHistoryCategory[finalCategories.size()]);
			return revisionsFound;
		}
		
		private MessageHistoryCategory getErrorMessage(){
			String message = ""; //$NON-NLS-1$
			switch(currentFilerMode){
				case LOCAL_MODE:
				message = CVSUIMessages.CVSHistoryPage_LocalModeTooltip;
				break;
				
				case REMOTE_MODE:
				message = CVSUIMessages.CVSHistoryPage_RemoteModeTooltip;
				break;
				
				case REMOTE_LOCAL_MODE:
				message = CVSUIMessages.CVSHistoryPage_NoRevisions;
				break;
			}
		 
			MessageHistoryCategory messageCategory = new MessageHistoryCategory(NLS.bind(CVSUIMessages.CVSHistoryPage_NoRevisionsForMode, new String[] { message }));
			return messageCategory;
		}

		public void setRefreshFlags(int refreshFlags) {
			this.refreshFlags = refreshFlags;
		}

	
		
	}
	
	
	/**
	 * A default content provider to prevent subclasses from
	 * having to implement methods they don't need.
	 */
	private class SimpleContentProvider implements IStructuredContentProvider {

		/**
		 * SimpleContentProvider constructor.
		 */
		public SimpleContentProvider() {
			super();
		}

		/*
		 * @see SimpleContentProvider#dispose()
		 */
		public void dispose() {
		}

		/*
		 * @see SimpleContentProvider#getElements()
		 */
		public Object[] getElements(Object element) {
			return new Object[0];
		}

		/*
		 * @see SimpleContentProvider#inputChanged()
		 */
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}
	}

	private class HistoryResourceListener implements IResourceChangeListener {
		/**
		 * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent)
		 */
		public void resourceChanged(IResourceChangeEvent event) {
			IResourceDelta root = event.getDelta();
			//Safety check for non-managed files that are added with the CVSHistoryPage
			//in view
			if (file == null ||	file.getIResource() == null)
				 return;
			
			IResourceDelta resourceDelta = root.findMember(((IFile)file.getIResource()).getFullPath());
			if (resourceDelta != null){
				String revision = getRevision();
				final boolean hasRevision = cvsFileHistory.getFileRevision(revision) != null;
				Display.getDefault().asyncExec(new Runnable() {
					public void run() {
						if (treeViewer.getControl().isDisposed())
							return;
						if (treeViewer.getControl().isVisible()) {
							if (hasRevision)
								refresh(CVSFileHistory.REFRESH_LOCAL);
							else
								refresh();
						} else {
							refreshRequest = hasRevision ? CVSFileHistory.REFRESH_LOCAL : CVSFileHistory.REFRESH_LOCAL | CVSFileHistory.REFRESH_REMOTE;
						}
					}
				});
			}
		}

		private String getRevision() {
			try {
				byte[] syncBytes = file.getSyncBytes();
				if (syncBytes != null && !ResourceSyncInfo.isAddition(syncBytes)) {
					return ResourceSyncInfo.getRevision(syncBytes);
				}
			} catch (CVSException e) {
				// Ignore the errors
			}
			return null;
		}
	}
		
	public Control getControl() {
		return sashForm;
	}

	public boolean isValidInput(Object object) {
		return getCVSFile(object) != null;
	}

	public String getName() {
		if (description != null)
			return description;
		if (file != null)
			return file.getName();
		
		return ""; //$NON-NLS-1$
	}
	
	/**
	 * Returns the path of the file currently being shown in the CVS History Page.
	 * @return an IPath or <code>null</code> if the file is null
	 */
	public IPath getFilePath() {
		if (file != null)
			return file.getIResource().getFullPath();
		
		return null;
	}

	public Object getAdapter(Class adapter) {
		if(adapter == IHistoryCompareAdapter.class) {
			return this;
		}
		return null;
	}

	public ICompareInput getCompareInput(Object object) {
		if (object instanceof IFileRevision){
			IFileRevision selectedFileRevision = (IFileRevision)object;
			if (fileElement == null)
				fileElement = SaveableCompareEditorInput.createFileElement((IFile) file.getIResource());
			FileRevisionTypedElement right = new FileRevisionTypedElement(selectedFileRevision, getLocalEncoding());
			DiffNode node = new DiffNode(fileElement, right);
			return node;
		}
		return null;
	}

	private String getLocalEncoding() {
		IResource resource = file.getIResource();
		if (resource instanceof IFile) {
			IFile file = (IFile) resource;
			try {
				return file.getCharset();
			} catch (CoreException e) {
				CVSUIPlugin.log(e);
			}
		}
		return null;
	}

	public void setClickAction(boolean compare) {
		//toggleCompareAction is going to switch the mode
		//so make sure that we're in the appropriate mode before
		compareMode = !compare;
		compareModeAction.run();
	}

	public void prepareInput(ICompareInput input, CompareConfiguration configuration, IProgressMonitor monitor) {
		initLabels(input, configuration);
		// TODO: pre-fetch contents
	}
	
	private void initLabels(ICompareInput input, CompareConfiguration cc) {
		String leftLabel = getFileRevisionLabel(input.getLeft(), cc);
		cc.setLeftLabel(leftLabel);
		String rightLabel = getFileRevisionLabel(input.getRight(), cc);
		cc.setRightLabel(rightLabel);
	}

	private String getFileRevisionLabel(ITypedElement element, CompareConfiguration cc) {
		String label = null;

		if (element instanceof IEditableContent) {
			//current revision
			if (element instanceof IModificationDate) {
				IModificationDate md = (IModificationDate) element;
				Date dateFromLong = new Date(md.getModificationDate());
				label = NLS.bind(TeamUIMessages.CompareFileRevisionEditorInput_workspace, new Object[]{ element.getName(), getDateTimeFormat().format(dateFromLong)});
			} else {
				label = element.getName();
			}
			return label;

		} else if (element instanceof FileRevisionTypedElement) {
			Object fileObject = ((FileRevisionTypedElement) element).getFileRevision();

			if (fileObject instanceof LocalFileRevision) {
				try {
					IStorage storage = ((LocalFileRevision) fileObject).getStorage(new NullProgressMonitor());
					if (Adapters.adapt(storage, IFileState.class) != null) {
						//local revision
						label = NLS.bind(TeamUIMessages.CompareFileRevisionEditorInput_localRevision, new Object[]{element.getName(), ((FileRevisionTypedElement) element).getTimestamp()});
					}
				} catch (CoreException e) {
				}
			} else {
				label = NLS.bind(
						TeamUIMessages.CompareFileRevisionEditorInput_repository,
						new Object[]{
								element.getName(),
								((FileRevisionTypedElement) element).getContentIdentifier(),
								((FileRevisionTypedElement) element).getAuthor()
								});
			}
		}
		return label;
	}
	
	private synchronized DateFormat getDateTimeFormat() {
		if (dateTimeFormat == null)
			dateTimeFormat = DateFormat.getDateTimeInstance();
		return dateTimeFormat;
	}

	public String getDescription() {
		try {
			if (file != null)
				return file.getRepositoryRelativePath();
		} catch (CVSException e) {
			// Ignore
		}
		return null;
	}

	public boolean inputSet() {
		//reset currentFileRevision
		currentFileRevision = null;
		Object inputObj = getInput();
	
		ICVSFile cvsFile = getCVSFile(inputObj);
		if (cvsFile == null)
			return false;
		
		this.file = cvsFile;
		fileElement = null;

		// if this input is the same as the last, we don't need to cancel
		// the current job
		boolean needRefresh = checkPreviousInput();
		printDebugInfo("CVSHistoryPage#inputSet, needRefresh = " + needRefresh, (IFile)cvsFile.getIResource(), cvsFileHistory, null); //$NON-NLS-1$
		if (refreshCVSFileHistoryJob != null) {
			if (!needRefresh && refreshCVSFileHistoryJob.getState() != Job.NONE) {
				// let the old job finish
				printDebugInfo("CVSHistoryPage#inputSet, the old job is still running", (IFile)cvsFile.getIResource(), cvsFileHistory, null); //$NON-NLS-1$
				return true;
			} else {
				// cancel the old job and continue
				printDebugInfo("CVSHistoryPage#inputSet, cancel the old job", (IFile)cvsFile.getIResource(), cvsFileHistory, null); //$NON-NLS-1$
				refreshCVSFileHistoryJob.cancel();
			}
		}
		
		refreshCVSFileHistoryJob = new RefreshCVSFileHistory(this);
		
		//if the input is a local file revision, pass it to the refresh job to
		//allow the refresh job to use it to match the time stamp of the local
		//files displayed in the history page
		if (inputObj instanceof CVSLocalFileRevision){
			refreshCVSFileHistoryJob.setLocalFileRevision((CVSLocalFileRevision) inputObj);
		} else if (inputObj instanceof IFile) {
			refreshCVSFileHistoryJob.setLocalFileRevision(new CVSLocalFileRevision((IFile) inputObj));
		}
		//let the refresh job know which flavour of select to use (ie. select CVSFileRevisions
		//or CVSLocalFileRevision)
		refreshCVSFileHistoryJob.setSelectLocal(inputObj instanceof CVSLocalFileRevision || inputObj instanceof IFile);
		
		
		//If the file history doesn't need to be refreshed, we can just
		//use the previous input file history
		if (needRefresh){
			cvsFileHistory = new CVSFileHistory(cvsFile);
			//fetch both local and remote revisions the first time around
			cvsFileHistory.includeLocalRevisions(true);
			//blank current input only after we're sure that we have a file
			//to fetch history for
			this.treeViewer.setInput(null);
			
			linkWithEditor();
		}
		
		//always refresh the history if the input gets set - in which
		//case set the selectOnly to false
		refreshHistory(needRefresh, !needRefresh, CVSFileHistory.REFRESH_LOCAL | CVSFileHistory.REFRESH_REMOTE);
		
		if (toggleSearchAction!= null && toggleSearchAction.isChecked()){
			searchField.selectAll();
		}
		
		return true;
	}
	

	
	/**
	 * @param page the workbench page that view and editor are contained in
	 * @param editor the editor to link to the history view
	 * @param historyView the history view to link to the editor
	 */
	public void linkWithEditor() {
		if (rulerSelectionListener != null) {
			rulerSelectionListener.dispose();
			rulerSelectionListener= null;
		}

		if (!getHistoryPageSite().isModal()) {
			IResource resource = file.getIResource();
			if (resource instanceof IFile) {
				IFile file = (IFile) resource;
				rulerSelectionListener= new CVSRevisionAnnotationController(getHistoryPageSite().getWorkbenchPageSite().getPage(), file);
			} else {
				Object input = getInput();
				if (input instanceof IStorageEditorInput) {
					IStorageEditorInput editorInput = (IStorageEditorInput) input;
					rulerSelectionListener= new CVSRevisionAnnotationController(getHistoryPageSite().getWorkbenchPageSite().getPage(), editorInput);
				}
			}
		}
	}
	
	/*
	 * Check to see if we need to refresh the input; if the previous file
	 * that was being shown
	 */
	private boolean checkPreviousInput() {
		
		if (previousFile != null){
			try {
				if (isSameRemote(file, previousFile)
					&& (isSameLocalFile(file, previousFile)
							|| (!isLocal(file) && isLocal(previousFile)))) {
					return false;
				}
			} catch (CVSException e) {
			}
		}
		
		//set previous file to current file
		previousFile = file;
		return true;
	}

	private boolean isLocal(ICVSFile file) {
		return file.getIResource() != null;
	}

	private boolean isSameLocalFile(ICVSFile file, ICVSFile previousFile) {
		IResource r1 = file.getIResource();
		IResource r2 = previousFile.getIResource();
		return r1 != null && r2 != null && r1.equals(r2);
	}

	private boolean isSameRemote(ICVSFile file, ICVSFile previousFile) throws CVSException {
		String path = file.getRepositoryRelativePath();
		String previousPath = previousFile.getRepositoryRelativePath();
		
		//Could be comparing two local files with no remotes
		if (path == null && previousPath == null)
			return true;
		
		return (path != null && previousPath != null && path.equals(previousPath) && isSameRepository(file.getParent(), previousFile.getParent()));
	}


	private boolean isSameRepository(ICVSFolder parent1, ICVSFolder parent2) {
		try {
			FolderSyncInfo info1 = parent1.getFolderSyncInfo();
			FolderSyncInfo info2 = parent2.getFolderSyncInfo();
			return (info1 != null && info2 != null && info1.getRemoteLocation().equals(info2.getRemoteLocation()));
		} catch (CVSException e) {
			// Ignore
		}
		return false;
	}

	private void updateFilterMode(int mode) {
		currentFilerMode=mode;
		switch(mode){
			case LOCAL_MODE:
				localFilteredOut = false;
				remoteFilteredOut = true;
				localMode.setChecked(true);
				remoteMode.setChecked(false);
				remoteLocalMode.setChecked(false);
				break;

			case REMOTE_MODE:
				localFilteredOut = true;
				remoteFilteredOut = false;
				localMode.setChecked(false);
				remoteMode.setChecked(true);
				remoteLocalMode.setChecked(false);
				break;

			case REMOTE_LOCAL_MODE:
				localFilteredOut = false;
				remoteFilteredOut = false;
				localMode.setChecked(false);
				remoteMode.setChecked(false);
				remoteLocalMode.setChecked(true);
				break;
		}

		//the refresh job gets created once the input is set
		//don't bother trying to refresh any history until the input has been set
		if (refreshCVSFileHistoryJob != null){
			//don't refetch, but not a select only job (ie. have to get the
			//existing revisions corresponding to the mode change)
			refreshHistory(false, false, CVSFileHistory.REFRESH_LOCAL | CVSFileHistory.REFRESH_REMOTE);
		}
	}

	public TreeViewer getTreeViewer() {
		return treeViewer;
	}

	public void showFilter(CVSHistoryFilter filter) {
		if (historyFilter != null)
			treeViewer.removeFilter(historyFilter);
		
		historyFilter = filter;
		int before = cvsFileHistory.getFileRevisions().length;
		treeViewer.addFilter(historyFilter);
		IHistoryPageSite historyPageSite =getHistoryPageSite();
		if (historyPageSite instanceof WorkbenchHistoryPageSite){
			IWorkbenchPart part = ((WorkbenchHistoryPageSite) historyPageSite).getPart();
			if (part instanceof GenericHistoryView){
				String revisions = NLS.bind(CVSUIMessages.CVSHistoryPage_FilterOnMessage, new Object[]{new Integer(historyFilter.getMatchCount()),new Integer(before)});
				String old = getName();
				description = NLS.bind(CVSUIMessages.CVSHistoryPage_FilterDescription, new Object[]{file.getName(), revisions});
				CVSHistoryPage.this.firePropertyChange(CVSHistoryPage.this, P_NAME, old, getName());
			}
		}
		toggleFilterAction.setEnabled(true);
	}
	
	/*
	 * Sets the filter mode for the page.
	 * param flag	LOCAL_MODE, REMOTE_MODE, REMOTE_LOCAL_MODE
	 */
	public void setMode(int flag){
		switch(flag){
			case LOCAL_MODE:
				localMode.setChecked(true);
				localMode.run();
				break;
			
			case REMOTE_MODE:
				remoteMode.setChecked(true);
				remoteMode.run();
				break;
				
			case REMOTE_LOCAL_MODE:
				remoteLocalMode.setChecked(true);
				remoteLocalMode.run();
				break;
		}
		
		//refetch revisions, not a select only job
		refreshHistory(true, false, CVSFileHistory.REFRESH_LOCAL | CVSFileHistory.REFRESH_REMOTE);
	}

	/**
	 * Save any changes that are buffered in the pages typed element.
	 * @param monitor a progress monitor.
	 * @throws CoreException
	 */
	public void saveChanges(IProgressMonitor monitor) throws CoreException {
		if (fileElement instanceof LocalResourceTypedElement) {
			LocalResourceTypedElement element = (LocalResourceTypedElement) fileElement;
			element.commit(monitor);
		}
	}

	private void setStatusLineMessage(String message) {
		IPageSite workbenchPageSite = getHistoryPageSite().getWorkbenchPageSite();
		if (workbenchPageSite != null) {
			workbenchPageSite.getActionBars().getStatusLineManager().setMessage(message);
		}
	}

	private static void printDebugInfo(String message, IFile file, CVSFileHistory history, Throwable t) {
		if (!Policy.DEBUG_HISTORY)
			return;
		String time= new SimpleDateFormat("m:ss.SSS").format(new Date(System.currentTimeMillis())); //$NON-NLS-1$
		String fileName= file != null ? file.getName() : "<workspaceFile == null>"; //$NON-NLS-1$
		String fileHistoryID= history != null ? history.toString() : "<fileHistory == null>"; //$NON-NLS-1$
		int i= fileHistoryID.indexOf('@');
		if (i != -1)
			fileHistoryID= fileHistoryID.substring(i);
		System.out.println(time + ": " + fileName + ", " + fileHistoryID + ": " + message); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		if (t != null)
			t.printStackTrace();
	}
}
