blob: 40fa24516064703bd31ba21a9efef9e20a275fb9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2018 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.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;
}
@Override
public void run() {
sortTagsAscending = sortAscending;
tagViewer.refresh();
}
}
@Override
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(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 = 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()) {
@Override
protected Map getHyperlinkDetectorTargets(ISourceViewer sourceViewer) {
return Collections.singletonMap("org.eclipse.ui.DefaultTextEditor", //$NON-NLS-1$
new IAdaptable() {
@Override
public <T> T getAdapter(Class<T> adapter) {
if(adapter==IFile.class && getInput() instanceof IFile) {
return adapter.cast(getInput());
} else if(adapter==IFileHistory.class && getInput() instanceof IFileHistory) {
return adapter.cast(getInput());
}
return Platform.getAdapterManager().getAdapter(CVSHistoryPage.this, adapter);
}
});
}
});
result.addSelectionChangedListener(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() {
@Override
public Object[] getElements(Object inputElement) {
if (inputElement == null)
return new Object[0];
ITag[] tags = (ITag[]) inputElement;
return tags;
}
});
result.setLabelProvider(new LabelProvider() {
@Override
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;
}
@Override
public String getText(Object element) {
return ((ITag) element).getName();
}
});
result.setComparator(new ViewerComparator() {
@Override
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(event -> {
copyTagAction.setEnabled(false);
if (event.getSelection() instanceof StructuredSelection) {
if (((StructuredSelection) event.getSelection()).getFirstElement() != null) {
copyTagAction.setEnabled(true);
}
}
});
return result;
}
@Override
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)) {
@Override
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)) {
@Override
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)) {
@Override
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)) {
@Override
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)){
@Override
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)) {
@Override
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)) {
@Override
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(){
@Override
public void widgetSelected(SelectionEvent e) {
//update the current
compareAction.setCurrentFileRevision(getCurrentFileRevision());
compareAction.selectionChanged(treeViewer.getStructuredSelection());
}
});
openAction = new OpenRevisionAction(CVSUIMessages.CVSHistoryPage_OpenAction, this);
openAction.setEnabled(!treeViewer.getSelection().isEmpty());
treeViewer.getTree().addSelectionListener(new SelectionAdapter(){
@Override
public void widgetSelected(SelectionEvent e) {
openAction.selectionChanged(treeViewer.getStructuredSelection());
}
});
// Add 'Open With...' sub-menu
openWithMenu = new OpenWithMenu(this);
treeViewer.getTree().addSelectionListener(new SelectionAdapter(){
@Override
public void widgetSelected(SelectionEvent e) {
openWithMenu.selectionChanged(treeViewer.getStructuredSelection());
}
});
new OpenAndLinkWithEditorHelper(treeViewer) {
@Override
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();
}
}
}
@Override
protected void activate(ISelection selection) {
int currentMode= OpenStrategy.getOpenMethod();
try {
OpenStrategy.setOpenMethod(OpenStrategy.DOUBLE_CLICK);
open(selection, true);
} finally {
OpenStrategy.setOpenMethod(currentMode);
}
}
@Override
protected void linkToEditor(ISelection selection) {
// XXX: Not yet implemented, see http://bugs.eclipse.org/324185
}
};
getContentsAction = getContextMenuAction(CVSUIMessages.HistoryView_getContentsAction, true /* needs progress */, monitor -> {
monitor.beginTask(null, 100);
try {
if(confirmOverwrite() && validateChange()) {
IStorage currentStorage = currentSelection.getStorage(SubMonitor.convert(monitor, 50));
InputStream in = currentStorage.getContents();
((IFile)file.getIResource()).setContents(in, false, true, SubMonitor.convert(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 */, monitor -> {
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(() -> refresh());
}
}
} catch (InvocationTargetException e1) {
throw CVSException.wrapException(e1);
} catch (InterruptedException e2) {
// 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() {
@Override
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
*/
@Override
protected ITagOperation createTagOperation() {
return new TagInRepositoryOperation(getTargetPart(), getSelectedRemoteResources()) {
@Override
public void execute(IProgressMonitor monitor) throws CVSException, InterruptedException {
super.execute(monitor);
Display.getDefault().asyncExec(() -> {
if( ! wasCancelled()) {
refresh();
}
});
};
};
}
};
tagWithExistingAction = getContextMenuAction(CVSUIMessages.HistoryView_tagWithExistingAction, false /* no progress */, monitor -> {
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) {
@Override
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) {
@Override
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) {
@Override
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) {
@Override
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){
@Override
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(menuMgr1 -> fillTableMenu(menuMgr1));
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(menuMgr1 -> fillTextMenu(menuMgr1));
StyledText text = textViewer.getTextWidget();
menu = menuMgr.createContextMenu(text);
text.setMenu(menu);
menuMgr = new MenuManager();
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(menuMgr1 -> fillTagMenu(menuMgr1));
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() {
@Override
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;
}
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
entries = null;
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof AbstractHistoryCategory){
return ((AbstractHistoryCategory) parentElement).getRevisions();
}
return null;
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
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(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) {
@Override
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, monitor -> {
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
}
}
@Override
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(() -> 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
*/
@Override
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 = 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 = Adapters.adapt(object, ICVSFile.class);
if (remoteFile != null) {
return remoteFile;
}
// Next, try ICVSResource
ICVSResource remote = Adapters.adapt(object, ICVSResource.class);
if (remote instanceof RemoteFile) {
return (ICVSFile)remote;
}
// Next, try IResourceVariant
IResourceVariant variant = Adapters.adapt(object, IResourceVariant.class);
if (variant instanceof RemoteFile) {
return (ICVSFile)remote;
}
// Finally, try IFileRevision
IFileRevision revision = 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();
}
@Override
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);
}
@Override
protected Object getHistoryEntry(Revision selected) {
return CVSHistoryPage.this.getFileRevision(selected.getId());
}
}
private final class SearchHistoryTable implements Runnable {
@Override
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;
}
@Override
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((Runnable) () -> {
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();
}
@Override
public void dispose() {
}
@Override
public Object[] getElements(Object element) {
return new Object[0];
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
private class HistoryResourceListener implements IResourceChangeListener {
/**
* @see IResourceChangeListener#resourceChanged(IResourceChangeEvent)
*/
@Override
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(() -> {
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;
}
}
@Override
public Control getControl() {
return sashForm;
}
@Override
public boolean isValidInput(Object object) {
return getCVSFile(object) != null;
}
@Override
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;
}
@Override
public <T> T getAdapter(Class<T> adapter) {
if(adapter == IHistoryCompareAdapter.class) {
return adapter.cast(this);
}
return null;
}
@Override
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();
}
@Override
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;
}
@Override
public String getDescription() {
try {
if (file != null)
return file.getRepositoryRelativePath();
} catch (CVSException e) {
// Ignore
}
return null;
}
@Override
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[]{Integer.valueOf(historyFilter.getMatchCount()),Integer.valueOf(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();
}
}