diff options
author | Bogdan Gheorghe | 2006-04-07 01:28:01 +0000 |
---|---|---|
committer | Bogdan Gheorghe | 2006-04-07 01:28:01 +0000 |
commit | a09b0a598d5fe8784f50387571f1d8e3934ee492 (patch) | |
tree | 18ca78e2866824d15ac9284da4aec3ee11d3e0d9 /bundles | |
parent | 0c847843c99cf8bf93aea2ba6aeb4933098fd376 (diff) | |
download | eclipse.platform.team-a09b0a598d5fe8784f50387571f1d8e3934ee492.tar.gz eclipse.platform.team-a09b0a598d5fe8784f50387571f1d8e3934ee492.tar.xz eclipse.platform.team-a09b0a598d5fe8784f50387571f1d8e3934ee492.zip |
Bug 127832 History view does not show local history for non-shared files
Diffstat (limited to 'bundles')
30 files changed, 1126 insertions, 350 deletions
diff --git a/bundles/org.eclipse.team.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.team.core/META-INF/MANIFEST.MF index f6d72151f..1cf808267 100644 --- a/bundles/org.eclipse.team.core/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.team.core/META-INF/MANIFEST.MF @@ -17,6 +17,7 @@ Export-Package: org.eclipse.team.core, org.eclipse.team.core.synchronize, org.eclipse.team.core.variants, org.eclipse.team.internal.core;x-friends:="org.eclipse.team.cvs.core,org.eclipse.team.cvs.ssh,org.eclipse.team.cvs.ssh2,org.eclipse.team.cvs.ui,org.eclipse.team.ui", + org.eclipse.team.internal.core.history, org.eclipse.team.internal.core.mapping;x-friends:="org.eclipse.team.cvs.core,org.eclipse.team.cvs.ssh,org.eclipse.team.cvs.ssh2,org.eclipse.team.cvs.ui,org.eclipse.team.ui", org.eclipse.team.internal.core.streams;x-friends:="org.eclipse.team.cvs.core,org.eclipse.team.cvs.ssh,org.eclipse.team.cvs.ssh2,org.eclipse.team.cvs.ui,org.eclipse.team.ui", org.eclipse.team.internal.core.subscribers;x-friends:="org.eclipse.team.cvs.core,org.eclipse.team.cvs.ssh,org.eclipse.team.cvs.ssh2,org.eclipse.team.cvs.ui,org.eclipse.team.ui" diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/Messages.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/Messages.java index 52da8f2c0..3a9b2d011 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/Messages.java +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/Messages.java @@ -15,6 +15,8 @@ import org.eclipse.osgi.util.NLS; public class Messages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.team.internal.core.messages";//$NON-NLS-1$ + public static String LocalFileHistory_RefreshLocalHistory; + public static String MergeContext_5; public static String MergeContext_6; diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/history/LocalFileHistory.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/history/LocalFileHistory.java new file mode 100644 index 000000000..5b0bdc087 --- /dev/null +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/history/LocalFileHistory.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.internal.core.history; + +import java.util.ArrayList; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFileState; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.history.IFileRevision; +import org.eclipse.team.core.history.provider.FileHistory; +import org.eclipse.team.internal.core.Messages; + +public class LocalFileHistory extends FileHistory { + + protected IFile file; + //used to hold all revisions (changes based on filtering) + protected IFileRevision[] revisions; + protected boolean refetchRevisions; + + /* + * Creates a new CVSFile history that will fetch remote revisions by default. + */ + public LocalFileHistory(IFile file) { + this.file = file; + this.refetchRevisions = true; + } + + public IFileRevision[] getContributors(IFileRevision revision) { + + IFileRevision[] revisions = getFileRevisions(); + + //the predecessor is the file with a timestamp that is the largest timestamp + //from the set of all timestamps smaller than the root file's timestamp + IFileRevision fileRevision = null; + for (int i = 0; i < revisions.length; i++) { + if (((LocalFileRevision) revisions[i]).isPredecessorOf(revision)) { + //no revision has been set as of yet + if (fileRevision == null) + fileRevision = revisions[i]; + //this revision is a predecessor - now check to see if it comes + //after the current predecessor, if it does make it the current predecessor + if (fileRevision != null && revisions[i].getTimestamp() > fileRevision.getTimestamp()) { + fileRevision = revisions[i]; + } + } + } + if (fileRevision == null) + return new IFileRevision[0]; + return new IFileRevision[] {fileRevision}; + } + + public IFileRevision getFileRevision(String id) { + // TODO Auto-generated method stub + return null; + } + + public IFileRevision[] getFileRevisions() { + if (revisions == null) + return new IFileRevision[0]; + return revisions; + } + + public IFileRevision[] getTargets(IFileRevision revision) { + IFileRevision[] revisions = getFileRevisions(); + ArrayList directDescendents = new ArrayList(); + + for (int i = 0; i < revisions.length; i++) { + if (((LocalFileRevision) revisions[i]).isDescendentOf(revision)) { + directDescendents.add(revisions[i]); + } + } + return (IFileRevision[]) directDescendents.toArray(new IFileRevision[directDescendents.size()]); + } + + /** + * Refreshes the revisions for this local file. + * + * @param monitor a progress monitor + * @throws TeamException + */ + public void refresh(IProgressMonitor monitor) throws TeamException { + if (refetchRevisions) { + monitor.beginTask(Messages.LocalFileHistory_RefreshLocalHistory/*, file.getProjectRelativePath().toString())*/, 300); + try { + IFileState[] fileStates = file.getHistory(monitor); + if (fileStates.length > 0) { + revisions = new LocalFileRevision[fileStates.length]; + for (int i = 0; i < fileStates.length; i++) { + revisions[i] = new LocalFileRevision(fileStates[i]); + } + } + + } catch (CoreException e) { + throw TeamException.asTeamException(e); + } finally { + monitor.done(); + } + } + } + +} diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/LocalFileRevision.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/history/LocalFileRevision.java index 2e9336770..582645aec 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/LocalFileRevision.java +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/history/LocalFileRevision.java @@ -8,7 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ -package org.eclipse.team.internal.core; +package org.eclipse.team.internal.core.history; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.CoreException; @@ -17,6 +17,7 @@ import org.eclipse.osgi.util.NLS; import org.eclipse.team.core.history.IFileRevision; import org.eclipse.team.core.history.ITag; import org.eclipse.team.core.history.provider.FileRevision; +import org.eclipse.team.internal.core.Messages; /** * A LocalFileRevision is used for wrapping local files in order to display @@ -138,4 +139,14 @@ public class LocalFileRevision extends FileRevision { public IFileRevision withAllProperties(IProgressMonitor monitor) { return this; } + + public boolean isPredecessorOf(IFileRevision revision) { + long compareRevisionTime = revision.getTimestamp(); + return (this.getTimestamp() < compareRevisionTime); + } + + public boolean isDescendentOf(IFileRevision revision) { + long compareRevisionTime = revision.getTimestamp(); + return (this.getTimestamp() > compareRevisionTime); + } } diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties index 2dec876f5..6e1bd64ca 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties @@ -92,6 +92,7 @@ DelegatingStorageMerger_1=An error occurred reading while reading from {0} LocalFileRevision_currentVersion=*({0}) LocalFileRevision_currentVersionTag=<current version> +LocalFileHistory_RefreshLocalHistory=Refreshing History for {0} LocalFileRevision_localRevisionTag=<local revision> WorkspaceSubscriber_0=Workspace WorkspaceSubscriber_1=Mulitple errors occurred diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/filehistory/CVSFileHistory.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/filehistory/CVSFileHistory.java index cdc71e4dc..ed5a62e24 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/filehistory/CVSFileHistory.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/filehistory/CVSFileHistory.java @@ -27,7 +27,7 @@ import org.eclipse.team.internal.ccvs.core.client.Session; import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; import org.eclipse.team.internal.ccvs.core.resources.RemoteFile; -import org.eclipse.team.internal.core.LocalFileRevision; +import org.eclipse.team.internal.core.history.LocalFileRevision; public class CVSFileHistory extends FileHistory { @@ -79,7 +79,6 @@ public class CVSFileHistory extends FileHistory { * Refreshes the revisions for this CVS file. It may or may not contact the server to get new revisions. * * @param monitor a progress monitor - * @return boolean true if operation terminated normally,false otherwise */ public void refresh(IProgressMonitor monitor) throws TeamException { if (refetchRevisions) { diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSHistoryFilter.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSHistoryFilter.java index e20c95576..bac40a1dc 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSHistoryFilter.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSHistoryFilter.java @@ -15,6 +15,7 @@ import java.util.Date; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.team.internal.ccvs.core.filehistory.CVSFileRevision; +import org.eclipse.team.internal.ui.history.AbstractHistoryCategory; public class CVSHistoryFilter extends ViewerFilter { public String author; @@ -35,7 +36,7 @@ public class CVSHistoryFilter extends ViewerFilter { * @see ViewerFilter#select(Viewer, Object, Object) */ public boolean select(Viewer aviewer, Object parentElement, Object element) { - if (element instanceof AbstractCVSHistoryCategory) + if (element instanceof AbstractHistoryCategory) return true; if (element instanceof CVSFileRevision) { diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSHistoryPage.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSHistoryPage.java index 37f2d4890..d79fede72 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSHistoryPage.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSHistoryPage.java @@ -53,9 +53,11 @@ import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; import org.eclipse.team.internal.ccvs.core.resources.RemoteFile; import org.eclipse.team.internal.ccvs.ui.actions.*; import org.eclipse.team.internal.ccvs.ui.operations.*; -import org.eclipse.team.internal.core.LocalFileRevision; +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.CompareRevisionAction; +import org.eclipse.team.internal.ui.actions.OpenRevisionAction; import org.eclipse.team.internal.ui.history.*; import org.eclipse.team.ui.history.*; import org.eclipse.ui.*; @@ -328,6 +330,8 @@ public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryC compareAction = new CompareRevisionAction(CVSUIMessages.CVSHistoryPage_CompareRevisionAction); treeViewer.getTree().addSelectionListener(new SelectionAdapter(){ public void widgetSelected(SelectionEvent e) { + //update the current + compareAction.setCurrentFileRevision(getCurrentFileRevision()); compareAction.selectionChanged((IStructuredSelection) treeViewer.getSelection()); } }); @@ -658,11 +662,11 @@ public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryC return entries; if (!(inputElement instanceof IFileHistory) && - !(inputElement instanceof AbstractCVSHistoryCategory[])) + !(inputElement instanceof AbstractHistoryCategory[])) return new Object[0]; - if (inputElement instanceof AbstractCVSHistoryCategory[]){ - return (AbstractCVSHistoryCategory[]) inputElement; + if (inputElement instanceof AbstractHistoryCategory[]){ + return (AbstractHistoryCategory[]) inputElement; } final IFileHistory fileHistory = (IFileHistory) inputElement; @@ -679,8 +683,8 @@ public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryC } public Object[] getChildren(Object parentElement) { - if (parentElement instanceof AbstractCVSHistoryCategory){ - return ((AbstractCVSHistoryCategory) parentElement).getRevisions(); + if (parentElement instanceof AbstractHistoryCategory){ + return ((AbstractHistoryCategory) parentElement).getRevisions(); } return null; @@ -691,8 +695,8 @@ public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryC } public boolean hasChildren(Object element) { - if (element instanceof AbstractCVSHistoryCategory){ - IFileRevision[] revs = ((AbstractCVSHistoryCategory) element).getRevisions(); + if (element instanceof AbstractHistoryCategory){ + IFileRevision[] revs = ((AbstractHistoryCategory) element).getRevisions(); if (revs != null) return revs.length > 0; } @@ -715,7 +719,7 @@ public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryC return; } Object o = ss.getFirstElement(); - if (o instanceof AbstractCVSHistoryCategory){ + if (o instanceof AbstractHistoryCategory){ textViewer.setDocument(new Document("")); //$NON-NLS-1$ tagViewer.setInput(null); return; @@ -739,7 +743,7 @@ public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryC IStructuredSelection ss = (IStructuredSelection)selection; Object o = ss.getFirstElement(); - if (o instanceof AbstractCVSHistoryCategory) + if (o instanceof AbstractHistoryCategory) return; currentSelection = (IFileRevision)o; @@ -963,7 +967,7 @@ public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryC private final static int NUMBER_OF_CATEGORIES = 4; private CVSFileHistory fileHistory; - private AbstractCVSHistoryCategory[] categories; + private AbstractHistoryCategory[] categories; private boolean grouping; private Object[] elementsToExpand; private boolean revisionsFound; @@ -1040,7 +1044,7 @@ public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryC treeViewer.getTree().setLinesVisible(true); treeViewer.setInput(fileHistory); } else { - categories = new AbstractCVSHistoryCategory[] {getErrorMessage()}; + categories = new AbstractHistoryCategory[] {getErrorMessage()}; treeViewer.getTree().setLinesVisible(false); treeViewer.setInput(categories); } @@ -1061,7 +1065,7 @@ public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryC //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(((DateCVSHistoryCategory)expandedElements[i]).getName(), null); + elementMap.put(((DateHistoryCategory)expandedElements[i]).getName(), null); } //Go through the new categories and keep track of the previously expanded ones @@ -1081,20 +1085,20 @@ public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryC IFileRevision[] fileRevision = fileHistory.getFileRevisions(); //Create the 4 categories - DateCVSHistoryCategory[] tempCategories = new DateCVSHistoryCategory[NUMBER_OF_CATEGORIES]; + DateHistoryCategory[] tempCategories = new DateHistoryCategory[NUMBER_OF_CATEGORIES]; //Get a calendar instance initialized to the current time Calendar currentCal = Calendar.getInstance(); - tempCategories[0] = new DateCVSHistoryCategory(CVSUIMessages.CVSHistoryPage_Today, currentCal, null); + 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 DateCVSHistoryCategory(CVSUIMessages.CVSHistoryPage_Yesterday, yesterdayCal, null); + tempCategories[1] = new DateHistoryCategory(CVSUIMessages.CVSHistoryPage_Yesterday, yesterdayCal, null); //Get last week Calendar lastWeekCal = Calendar.getInstance(); lastWeekCal.roll(Calendar.DAY_OF_YEAR, -7); - tempCategories[2] = new DateCVSHistoryCategory(CVSUIMessages.CVSHistoryPage_LastWeek, lastWeekCal, yesterdayCal); + tempCategories[2] = new DateHistoryCategory(CVSUIMessages.CVSHistoryPage_LastWeek, lastWeekCal, yesterdayCal); //Everything before after week is previous - tempCategories[3] = new DateCVSHistoryCategory(CVSUIMessages.CVSHistoryPage_Previous, null, lastWeekCal); + tempCategories[3] = new DateHistoryCategory(CVSUIMessages.CVSHistoryPage_Previous, null, lastWeekCal); ArrayList finalCategories = new ArrayList(); for (int i = 0; i<NUMBER_OF_CATEGORIES; i++){ @@ -1112,11 +1116,11 @@ public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryC revisionsFound = false; } - categories = (AbstractCVSHistoryCategory[])finalCategories.toArray(new AbstractCVSHistoryCategory[finalCategories.size()]); + categories = (AbstractHistoryCategory[])finalCategories.toArray(new AbstractHistoryCategory[finalCategories.size()]); return revisionsFound; } - private MessageCVSHistoryCategory getErrorMessage(){ + private MessageHistoryCategory getErrorMessage(){ String message = ""; //$NON-NLS-1$ switch(currentFilerMode){ case LOCAL_MODE: @@ -1132,7 +1136,7 @@ public class CVSHistoryPage extends HistoryPage implements IAdaptable, IHistoryC break; } - MessageCVSHistoryCategory messageCategory = new MessageCVSHistoryCategory(NLS.bind(CVSUIMessages.CVSHistoryPage_NoRevisionsForMode, new String[] { message })); + MessageHistoryCategory messageCategory = new MessageHistoryCategory(NLS.bind(CVSUIMessages.CVSHistoryPage_NoRevisionsForMode, new String[] { message })); return messageCategory; } } diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSHistoryTableProvider.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSHistoryTableProvider.java index ad032a9ea..737feea03 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSHistoryTableProvider.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSHistoryTableProvider.java @@ -30,8 +30,10 @@ import org.eclipse.team.core.history.*; import org.eclipse.team.internal.ccvs.core.CVSException; import org.eclipse.team.internal.ccvs.core.ICVSFile; import org.eclipse.team.internal.ccvs.core.filehistory.CVSFileRevision; -import org.eclipse.team.internal.core.LocalFileRevision; +import org.eclipse.team.internal.core.history.LocalFileRevision; import org.eclipse.team.internal.ui.TeamUIMessages; +import org.eclipse.team.internal.ui.history.AbstractHistoryCategory; +import org.eclipse.team.internal.ui.history.DateHistoryCategory; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.themes.ITheme; @@ -95,7 +97,7 @@ public class CVSHistoryTableProvider { } public Image getColumnImage(Object element, int columnIndex) { - if (element instanceof DateCVSHistoryCategory && + if (element instanceof DateHistoryCategory && columnIndex == COL_REVISIONID){ if (dateImage == null){ dateDesc = CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_DATES_CATEGORY); @@ -128,11 +130,11 @@ public class CVSHistoryTableProvider { } public String getColumnText(Object element, int columnIndex) { - if (element instanceof AbstractCVSHistoryCategory){ + if (element instanceof AbstractHistoryCategory){ if (columnIndex != COL_REVISIONID) return ""; //$NON-NLS-1$ - return ((AbstractCVSHistoryCategory) element).getName(); + return ((AbstractHistoryCategory) element).getName(); } IFileRevision entry = adaptToFileRevision(element); @@ -186,7 +188,7 @@ public class CVSHistoryTableProvider { * @see org.eclipse.jface.viewers.IColorProvider#getForeground(java.lang.Object) */ public Color getForeground(Object element) { - if (element instanceof AbstractCVSHistoryCategory){ + if (element instanceof AbstractHistoryCategory){ ITheme current = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme(); return current.getColorRegistry().get(CVSHistoryTableProvider.CATEGORIES_COLOR); } @@ -211,7 +213,7 @@ public class CVSHistoryTableProvider { * @see org.eclipse.jface.viewers.IFontProvider#getFont(java.lang.Object) */ public Font getFont(Object element) { - if (element instanceof AbstractCVSHistoryCategory) { + if (element instanceof AbstractHistoryCategory) { return getCurrentRevisionFont(); } @@ -270,7 +272,7 @@ public class CVSHistoryTableProvider { * then by subsequent columns, depending on the column sort order. */ public int compare(Viewer compareViewer, Object o1, Object o2) { - if (o1 instanceof AbstractCVSHistoryCategory || o2 instanceof AbstractCVSHistoryCategory) + if (o1 instanceof AbstractHistoryCategory || o2 instanceof AbstractHistoryCategory) return 0; IFileRevision e1 = adaptToFileRevision(o1); @@ -381,8 +383,8 @@ public class CVSHistoryTableProvider { entry = (IFileRevision) element; } else if (element instanceof IAdaptable) { entry = (IFileRevision) ((IAdaptable) element).getAdapter(IFileRevision.class); - } else if (element instanceof AbstractCVSHistoryCategory){ - entry = ((AbstractCVSHistoryCategory) element).getRevisions()[0]; + } else if (element instanceof AbstractHistoryCategory){ + entry = ((AbstractHistoryCategory) element).getRevisions()[0]; } return entry; } diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIMessages.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIMessages.java index 313adc0d7..abe0f4f7f 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIMessages.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIMessages.java @@ -35,18 +35,12 @@ public class CVSUIMessages extends NLS { public static String CommitAction_0; public static String CommitAction_1; public static String CommitAction_2; - public static String CompareRevisionAction_Local; - public static String CompareRevisionAction_Revision; public static String CVSHistoryPage_CollapseAllAction; public static String CVSHistoryPage_CollapseAllTooltip; public static String CVSHistoryPage_CompareModeTooltip; public static String CVSHistoryPage_FilterOn; public static String CVSPreferencesPage_46; public static String CVSPreferencesPage_QuickDiffAnnotate; - public static String OpenRevisionAction_DeletedRevMessage; - public static String OpenRevisionAction_DeletedRevTitle; - public static String OpenRevisionAction_ErrorMessage; - public static String OpenRevisionAction_ErrorTitle; public static String PasswordManagementPreferencePage_2; public static String PasswordManagementPreferencePage_3; public static String PasswordManagementPreferencePage_4; @@ -1089,10 +1083,7 @@ public class CVSUIMessages extends NLS { public static String CVSHistoryPage_CompareRevisionAction; public static String CVSHistoryPage_CompareModeToggleAction; public static String CVSHistoryPage_FilterHistoryTooltip; - public static String CompareRevisionAction_CompareWithCurrent; - public static String CompareRevisionAction_CompareWithOther; public static String CVSHistoryPage_OpenAction; - public static String CompareRevisionAction_DeleteCompareMessage; public static String CVSHistoryPage_GroupByDate; public static String CVSHistoryPage_Today; public static String CVSHistoryPage_Yesterday; diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/messages.properties b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/messages.properties index 1ed720f9c..4bea5e33d 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/messages.properties +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/messages.properties @@ -102,7 +102,6 @@ CVSCompareRevisionsInput_compareResourceAndVersions=Revisions of ''{0}'' CVSCompareRevisionsInput_repository=Repository file: {0} CVSCompareRevisionsInput_workspace=Workspace file: {0} CVSCompareRevisionsInput_truncate={0}[...] -CompareRevisionAction_DeleteCompareMessage=One of the revisions represents a deletion and cannot be compared. CVSDecoratorPreferencesPage_0=Select the &variables to add to the decoration format: CVSDecoratorPreferencesPage_1=Add Variables @@ -1041,10 +1040,6 @@ CVSHistoryPage_CollapseAllAction=Collapse All CVSHistoryPage_CollapseAllTooltip=Collapse All CVSHistoryPage_NoRevisionsForMode=No {0} CVSHistoryPage_NoRevisions=Revisions -CompareRevisionAction_CompareWithCurrent=&Compare with Current Revision -CompareRevisionAction_CompareWithOther=&Compare with Each Other -CompareRevisionAction_Revision=Compare Current with {0} -CompareRevisionAction_Local=Compare Current with Local CVSTeamProvider_makeBranch=Creating branch CVSTeamProvider_folderInfo=Updating folder synchronization information for project {0} CVSTeamProvider_updatingFolder=Updating {0} @@ -1129,7 +1124,3 @@ OutgoingChangesDialog_0=An error occurred creating the details section. OutgoingChangesDialog_1=Creation of the details section was canceled. SyncAction_0=Synchronizing CVS SyncAction_1=Should change sets be consulted to determine which resources should be included in the synchronization? -OpenRevisionAction_DeletedRevTitle=Deleted Revision -OpenRevisionAction_ErrorTitle=Open Revision -OpenRevisionAction_ErrorMessage=An error occurred while trying to open the revision. -OpenRevisionAction_DeletedRevMessage=This revision represents a deletion and cannot be opened. diff --git a/bundles/org.eclipse.team.ui/icons/full/eview16/compare_view.gif b/bundles/org.eclipse.team.ui/icons/full/eview16/compare_view.gif Binary files differnew file mode 100644 index 000000000..dc549bce8 --- /dev/null +++ b/bundles/org.eclipse.team.ui/icons/full/eview16/compare_view.gif diff --git a/bundles/org.eclipse.team.ui/icons/full/obj/dates.gif b/bundles/org.eclipse.team.ui/icons/full/obj/dates.gif Binary files differnew file mode 100644 index 000000000..96aae05cb --- /dev/null +++ b/bundles/org.eclipse.team.ui/icons/full/obj/dates.gif diff --git a/bundles/org.eclipse.team.ui/icons/full/obj/local_entry_tbl.gif b/bundles/org.eclipse.team.ui/icons/full/obj/local_entry_tbl.gif Binary files differnew file mode 100644 index 000000000..4822bf86c --- /dev/null +++ b/bundles/org.eclipse.team.ui/icons/full/obj/local_entry_tbl.gif diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/IPreferenceIds.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/IPreferenceIds.java index c1a45ecc8..9108ab062 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/IPreferenceIds.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/IPreferenceIds.java @@ -65,4 +65,10 @@ public interface IPreferenceIds { * Preference to determine if the workspace is started for the first time. */ public static final String PREF_WORKSPACE_FIRST_TIME = PREFIX + "first_time"; //$NON-NLS-1$ + + /* + * Preferences for the Local History Page + */ + public static final String PREF_GROUPBYDATE_MODE = PREFIX + "group_bydate_mode"; //$NON-NLS-1$ + } diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ITeamUIImages.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ITeamUIImages.java index 75e816239..13e08992e 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ITeamUIImages.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/ITeamUIImages.java @@ -183,6 +183,13 @@ public interface ITeamUIImages { public final String IMG_FLAT = "elcl16/flatLayout.gif"; //$NON-NLS-1$ public final String IMG_SYNC_VIEW = "eview16/synch_synch.gif"; //$NON-NLS-1$ public final String IMG_CHANGE_SET = "obj/changeset_obj.gif"; //$NON-NLS-1$ + + /** + * Images used by the Local History Page + */ + public final String IMG_COMPARE_VIEW = "eview16/compare_view.gif"; //$NON-NLS-1$ + public final String IMG_DATES_CATEGORY = "obj/dates.gif"; //$NON-NLS-1$ + public final String IMG_LOCALREVISION_TABLE = "obj/local_entry_tbl.gif"; //$NON-NLS-1$ } diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIMessages.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIMessages.java index b71020e7e..b83cc1492 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIMessages.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIMessages.java @@ -72,6 +72,26 @@ public class TeamUIMessages extends NLS { public static String IgnorePreferencePage_patternExistsShort; public static String IgnorePreferencePage_remove; + public static String LocalHistoryPage_CollapseAllAction; + + public static String LocalHistoryPage_CollapseAllTip; + + public static String LocalHistoryPage_CompareAction; + + public static String LocalHistoryPage_CompareModeAction; + + public static String LocalHistoryPage_CompareModeTip; + + public static String LocalHistoryPage_FetchLocalHistoryMessage; + + public static String LocalHistoryPage_GroupRevisionsByDateAction; + + public static String LocalHistoryPage_GroupRevisionsByDateTip; + + public static String LocalHistoryPage_NoRevisionsFound; + + public static String LocalHistoryPage_OpenAction; + public static String MergeAllActionHandler_0; public static String MergeAllActionHandler_1; @@ -501,4 +521,20 @@ public class TeamUIMessages extends NLS { public static String CompareFileRevisionEditorInput_2; public static String SynchronizationCompareAdapter_0; + + public static String HistoryPage_Today; + public static String HistoryPage_Yesterday; + public static String HistoryPage_LastWeek; + public static String HistoryPage_Previous; + + public static String OpenRevisionAction_DeletedRevTitle; + public static String OpenRevisionAction_ErrorTitle; + public static String OpenRevisionAction_ErrorMessage; + public static String OpenRevisionAction_DeletedRevMessage; + + public static String CompareRevisionAction_DeleteCompareMessage; + public static String CompareRevisionAction_CompareWithCurrent; + public static String CompareRevisionAction_CompareWithOther; + public static String CompareRevisionAction_Revision; + public static String CompareRevisionAction_Local; } diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIPlugin.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIPlugin.java index 42890bc31..015b8fa3b 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIPlugin.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIPlugin.java @@ -360,6 +360,11 @@ public class TeamUIPlugin extends AbstractUIPlugin { createImageDescriptor(plugin, ITeamUIImages.IMG_COMPRESSED_FOLDER); createImageDescriptor(plugin, ITeamUIImages.IMG_SYNC_VIEW); createImageDescriptor(plugin, ITeamUIImages.IMG_HIERARCHICAL); + + // Local History Page + createImageDescriptor(plugin, ITeamUIImages.IMG_DATES_CATEGORY); + createImageDescriptor(plugin, ITeamUIImages.IMG_COMPARE_VIEW); + createImageDescriptor(plugin, ITeamUIImages.IMG_LOCALREVISION_TABLE); } private URL getImageUrl(String relative) { diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareRevisionAction.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/actions/CompareRevisionAction.java index 57bd1e1cd..081413aa2 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareRevisionAction.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/actions/CompareRevisionAction.java @@ -9,7 +9,7 @@ * IBM Corporation - initial API and implementation *******************************************************************************/ -package org.eclipse.team.internal.ccvs.ui.actions; +package org.eclipse.team.internal.ui.actions; import org.eclipse.compare.CompareEditorInput; import org.eclipse.compare.CompareUI; @@ -17,11 +17,11 @@ import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.osgi.util.NLS; import org.eclipse.team.core.history.IFileRevision; -import org.eclipse.team.internal.ccvs.core.filehistory.CVSFileRevision; -import org.eclipse.team.internal.ccvs.ui.*; -import org.eclipse.team.internal.core.LocalFileRevision; -import org.eclipse.team.internal.ui.history.CompareFileRevisionEditorInput; -import org.eclipse.team.internal.ui.history.FileRevisionTypedElement; +import org.eclipse.team.core.history.provider.FileRevision; +import org.eclipse.team.internal.core.history.LocalFileRevision; +import org.eclipse.team.internal.ui.TeamUIMessages; +import org.eclipse.team.internal.ui.history.*; +import org.eclipse.team.ui.history.HistoryPage; import org.eclipse.ui.*; import org.eclipse.ui.actions.BaseSelectionListenerAction; @@ -31,8 +31,9 @@ public class CompareRevisionAction extends BaseSelectionListenerAction { super(text); } - CVSHistoryPage page; + HistoryPage page; IStructuredSelection selection; + IFileRevision currentFileRevision; public void run() { try { @@ -44,7 +45,7 @@ public class CompareRevisionAction extends BaseSelectionListenerAction { switch (structSel.size()){ case 1: - file1 = page.getCurrentFileRevision(); + file1 = getCurrentFileRevision(); Object tempRevision = objArray[0]; if (tempRevision instanceof IFileRevision) file2 = (IFileRevision) tempRevision; @@ -67,7 +68,7 @@ public class CompareRevisionAction extends BaseSelectionListenerAction { if (file1 == null || file2 == null || !file1.exists() || !file2.exists()){ - MessageDialog.openError(page.getSite().getShell(), CVSUIMessages.OpenRevisionAction_DeletedRevTitle, CVSUIMessages.CompareRevisionAction_DeleteCompareMessage); + MessageDialog.openError(page.getSite().getShell(), TeamUIMessages.OpenRevisionAction_DeletedRevTitle, TeamUIMessages.CompareRevisionAction_DeleteCompareMessage); return; } @@ -94,9 +95,19 @@ public class CompareRevisionAction extends BaseSelectionListenerAction { } } + private IFileRevision getCurrentFileRevision() { + return currentFileRevision; + } + + public void setCurrentFileRevision(IFileRevision fileRevision){ + this.currentFileRevision = fileRevision; + } + /** * Returns an editor that can be re-used. An open compare editor that * has un-saved changes cannot be re-used. + * @param page + * @return an EditorPart or <code>null</code> if none can be found */ public static IEditorPart findReusableCompareEditor(IWorkbenchPage page) { IEditorReference[] editorRefs = page.getEditorReferences(); @@ -117,23 +128,24 @@ public class CompareRevisionAction extends BaseSelectionListenerAction { this.selection = selection; if (selection.size() == 1){ Object el = selection.getFirstElement(); - if (el instanceof CVSFileRevision){ - CVSFileRevision tempFileRevision = (CVSFileRevision) el; - this.setText(NLS.bind(CVSUIMessages.CompareRevisionAction_Revision, new String[]{tempFileRevision.getContentIdentifier()})); - } else if (el instanceof LocalFileRevision) - this.setText(CVSUIMessages.CompareRevisionAction_Local); + if (el instanceof LocalFileRevision) + this.setText(TeamUIMessages.CompareRevisionAction_Local); + else if (el instanceof FileRevision){ + FileRevision tempFileRevision = (FileRevision) el; + this.setText(NLS.bind(TeamUIMessages.CompareRevisionAction_Revision, new String[]{tempFileRevision.getContentIdentifier()})); + } else - this.setText(CVSUIMessages.CompareRevisionAction_CompareWithCurrent); + this.setText(TeamUIMessages.CompareRevisionAction_CompareWithCurrent); return shouldShow(); } else if (selection.size() == 2){ - this.setText(CVSUIMessages.CompareRevisionAction_CompareWithOther); + this.setText(TeamUIMessages.CompareRevisionAction_CompareWithOther); return shouldShow(); } return false; } - public void setPage(CVSHistoryPage page) { + public void setPage(HistoryPage page) { this.page = page; } @@ -147,7 +159,7 @@ public class CompareRevisionAction extends BaseSelectionListenerAction { for (int i = 0; i < objArray.length; i++) { //Don't bother showing if this a category - if (objArray[i] instanceof AbstractCVSHistoryCategory) + if (objArray[i] instanceof AbstractHistoryCategory) return false; IFileRevision revision = (IFileRevision) objArray[i]; diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/OpenRevisionAction.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/actions/OpenRevisionAction.java index 0a9301f16..79819b68e 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/OpenRevisionAction.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/actions/OpenRevisionAction.java @@ -9,7 +9,7 @@ * IBM Corporation - initial API and implementation *******************************************************************************/ -package org.eclipse.team.internal.ccvs.ui.actions; +package org.eclipse.team.internal.ui.actions; import java.io.IOException; import java.io.InputStream; @@ -22,9 +22,10 @@ import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.team.core.history.IFileRevision; -import org.eclipse.team.internal.ccvs.ui.*; -import org.eclipse.team.internal.ui.TeamUIPlugin; +import org.eclipse.team.internal.ui.*; +import org.eclipse.team.internal.ui.history.AbstractHistoryCategory; import org.eclipse.team.internal.ui.history.FileRevisionEditorInput; +import org.eclipse.team.ui.history.HistoryPage; import org.eclipse.ui.*; import org.eclipse.ui.actions.BaseSelectionListenerAction; import org.eclipse.ui.progress.IProgressService; @@ -32,7 +33,7 @@ import org.eclipse.ui.progress.IProgressService; public class OpenRevisionAction extends BaseSelectionListenerAction { private IStructuredSelection selection; - private CVSHistoryPage page; + private HistoryPage page; public OpenRevisionAction(String text) { super(text); @@ -46,12 +47,12 @@ public class OpenRevisionAction extends BaseSelectionListenerAction { for (int i = 0; i < objArray.length; i++) { Object tempRevision = objArray[i]; //If not a revision, don't try opening - if (tempRevision instanceof AbstractCVSHistoryCategory) + if (tempRevision instanceof AbstractHistoryCategory) continue; final IFileRevision revision = (IFileRevision) tempRevision; if (revision == null || !revision.exists()) { - MessageDialog.openError(page.getSite().getShell(), CVSUIMessages.OpenRevisionAction_DeletedRevTitle, CVSUIMessages.OpenRevisionAction_DeletedRevMessage); + MessageDialog.openError(page.getSite().getShell(), TeamUIMessages.OpenRevisionAction_DeletedRevTitle, TeamUIMessages.OpenRevisionAction_DeletedRevMessage); } else { IRunnableWithProgress runnable = new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { @@ -73,7 +74,7 @@ public class OpenRevisionAction extends BaseSelectionListenerAction { try { progressService.run(false, false, runnable); } catch (InvocationTargetException e) { - CVSUIPlugin.openError(page.getSite().getShell(), CVSUIMessages.OpenRevisionAction_ErrorTitle, CVSUIMessages.OpenRevisionAction_ErrorMessage, e); + Utils.handleError(page.getSite().getShell(), e, TeamUIMessages.OpenRevisionAction_ErrorTitle, TeamUIMessages.OpenRevisionAction_ErrorMessage); } catch (InterruptedException e) { } } @@ -111,7 +112,7 @@ public class OpenRevisionAction extends BaseSelectionListenerAction { return shouldShow(); } - public void setPage(CVSHistoryPage page) { + public void setPage(HistoryPage page) { this.page = page; } @@ -124,7 +125,7 @@ public class OpenRevisionAction extends BaseSelectionListenerAction { for (int i = 0; i < objArray.length; i++) { //Don't bother showing if this a category - if (objArray[i] instanceof AbstractCVSHistoryCategory) + if (objArray[i] instanceof AbstractHistoryCategory) return false; IFileRevision revision = (IFileRevision) objArray[i]; diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/AbstractCVSHistoryCategory.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/AbstractHistoryCategory.java index d0ba867df..46e5229fb 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/AbstractCVSHistoryCategory.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/AbstractHistoryCategory.java @@ -8,20 +8,16 @@ * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ -package org.eclipse.team.internal.ccvs.ui; +package org.eclipse.team.internal.ui.history; import org.eclipse.swt.graphics.Image; import org.eclipse.team.core.history.IFileRevision; -/** - * Provides an abstract representation of a category that can be used in the - * CVS History Page to provide grouping for IFileRevisions. - */ -public abstract class AbstractCVSHistoryCategory { + +public abstract class AbstractHistoryCategory { /** - * Returns the name of this category. This is used to display the category - * in the CVS History Page. + * Returns the name of this category. * @return a string */ abstract public String getName(); @@ -34,13 +30,19 @@ public abstract class AbstractCVSHistoryCategory { public Image getImage() { return null; } + + /** + * Returns whether this category currently has any revisions associated with it. + * @return <code>true</code> if there are any revisions, <code>false</code> otherwise. + */ + abstract public boolean hasRevisions(); /** * Takes in an array of IFileRevision and collects the revisions that belong to this category. * The shouldRemove flag indicates whether match file revisions need to be removed from the * passed in file revision array (in order to increase efficency). * @param fileRevisions an array of IFileRevisions - * @param canRemove <code>true</code> if the method should remove the matching revisions from fileRevisions, <code>false</code> otherwise + * @param shouldRemove <code>true</code> if the method should remove the matching revisions from fileRevisions, <code>false</code> otherwise * @return <code>true</code> if any revisions match this category, <code>false</code> otherwise */ abstract public boolean collectFileRevisions(IFileRevision[] fileRevisions, boolean shouldRemove); @@ -51,11 +53,4 @@ public abstract class AbstractCVSHistoryCategory { * @return an array of IFileRevision or <code>null</code> */ abstract public IFileRevision[] getRevisions(); - - /** - * Returns whether this category currently has any revisions associated with it. - * @return <code>true</code> if there are any revisions, <code>false</code> otherwise. - */ - abstract public boolean hasRevisions(); - } diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/CompareFileRevisionEditorInput.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/CompareFileRevisionEditorInput.java index c9a939ff5..93304a8c3 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/CompareFileRevisionEditorInput.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/CompareFileRevisionEditorInput.java @@ -18,7 +18,7 @@ import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Composite; -import org.eclipse.team.internal.core.LocalFileRevision; +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.ui.ISaveableWorkbenchPart; @@ -40,6 +40,8 @@ public class CompareFileRevisionEditorInput extends CompareEditorInput implement /** * Creates a new CompareFileRevisionEditorInput. + * @param left + * @param right */ public CompareFileRevisionEditorInput(FileRevisionTypedElement left, FileRevisionTypedElement right) { super(new CompareConfiguration()); diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/DateCVSHistoryCategory.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/DateHistoryCategory.java index 3c18d71a7..d0ff76735 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/DateCVSHistoryCategory.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/DateHistoryCategory.java @@ -8,13 +8,13 @@ * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ -package org.eclipse.team.internal.ccvs.ui; +package org.eclipse.team.internal.ui.history; import java.util.*; import org.eclipse.team.core.history.IFileRevision; -public class DateCVSHistoryCategory extends AbstractCVSHistoryCategory { +public class DateHistoryCategory extends AbstractHistoryCategory { private String name; private Calendar fromDate; @@ -29,9 +29,8 @@ public class DateCVSHistoryCategory extends AbstractCVSHistoryCategory { * @param fromDate the start date for this category or <code>null</code> if you want everything up to the end date * @param toDate the end point for this category or <code>null</code> if you want just all entries in the * start date - * @param mode the comparison constant which indicated wheth */ - public DateCVSHistoryCategory(String name, Calendar fromDate, Calendar toDate){ + public DateHistoryCategory(String name, Calendar fromDate, Calendar toDate){ this.name = name; this.fromDate = fromDate; this.toDate = toDate; diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/GenericHistoryView.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/GenericHistoryView.java index dd68b863a..d220507f3 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/GenericHistoryView.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/GenericHistoryView.java @@ -444,17 +444,20 @@ public class GenericHistoryView extends ViewPart implements IHistoryView { //check to see if resource is managed RepositoryProvider teamProvider = RepositoryProvider.getProvider(resource.getProject()); //couldn't find a repo provider; try showing it in a local page - if (teamProvider == null){ - return localItemDropped(resource); - } - IFileHistoryProvider fileHistory = teamProvider.getFileHistoryProvider(); Object tempPageSource = null; - if (fileHistory != null) { - tempPageSource = Utils.getAdapter(fileHistory, IHistoryPageSource.class,true); - } - if (tempPageSource == null) { - tempPageSource = Utils.getAdapter(teamProvider, IHistoryPageSource.class,true); + if (teamProvider == null){ + tempPageSource = new LocalHistoryPageSource(); + } else { + IFileHistoryProvider fileHistory = teamProvider.getFileHistoryProvider(); + + if (fileHistory != null) { + tempPageSource = Utils.getAdapter(fileHistory, IHistoryPageSource.class,true); + } + if (tempPageSource == null) { + tempPageSource = Utils.getAdapter(teamProvider, IHistoryPageSource.class,true); + } } + if (tempPageSource instanceof IHistoryPageSource) { IHistoryPageSource pageSource = (IHistoryPageSource) tempPageSource; @@ -619,16 +622,6 @@ public class GenericHistoryView extends ViewPart implements IHistoryView { container.setSubBars((SubActionBars) site.getActionBars()); return container; } - - protected PageContainer createLocalPage(PageBook book){ - LocalHistoryPage page = new LocalHistoryPage(); - PageSite site = initPage(page); - ((IHistoryPage) page).setSite(new WorkbenchHistoryPageSite(this, page.getSite())); - page.createControl(book); - PageContainer container = new PageContainer(page); - container.setSubBars((SubActionBars) site.getActionBars()); - return container; - } /** * An editor has been activated. Fetch the history if the file is shared and the history view @@ -684,18 +677,6 @@ public class GenericHistoryView extends ViewPart implements IHistoryView { HistoryManagerInstanceManager.getManager().deregister(this);*/ } - public IHistoryPage localItemDropped(IResource resource) { - PageContainer container = createLocalPage(this.book); - IHistoryPage localPage = (IHistoryPage) container.getPage(); - if (localPage.setInput(resource)){ - setContentDescription(resource.getName()); - showPageRec(container); - return localPage; - } - - return null; - } - public IHistoryPage showHistoryFor(Object object) { return itemDropped(object, true); } diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/LocalHistoryPage.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/LocalHistoryPage.java index fc281135f..d6582b9cb 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/LocalHistoryPage.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/LocalHistoryPage.java @@ -10,195 +10,361 @@ *******************************************************************************/ package org.eclipse.team.internal.ui.history; + +import java.util.*; + import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.*; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IOpenEventListener; +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.layout.FillLayout; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; -import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.TeamStatus; +import org.eclipse.team.core.history.IFileHistory; +import org.eclipse.team.core.history.IFileRevision; +import org.eclipse.team.internal.core.history.LocalFileHistory; +import org.eclipse.team.internal.core.history.LocalFileRevision; import org.eclipse.team.internal.ui.*; +import org.eclipse.team.internal.ui.actions.CompareRevisionAction; +import org.eclipse.team.internal.ui.actions.OpenRevisionAction; import org.eclipse.team.ui.history.HistoryPage; +import org.eclipse.team.ui.history.IHistoryPageSite; import org.eclipse.ui.*; +import org.eclipse.ui.progress.IProgressConstants; public class LocalHistoryPage extends HistoryPage { - - Composite pgComp; - TableViewer tableViewer; - LocalHistoryTableProvider historyTableProvider; - /* private */boolean shutdown = false; + /* private */ IFile file; + /* private */ IFileRevision currentFileRevision; + // cached for efficiency - /* private */IFileState[] entries; + /* private */ LocalFileHistory localFileHistory; + /* private */IFileRevision[] entries; - protected FetchLocalHistoryJob fetchLocalHistoryJob; + /* private */ TreeViewer treeViewer; - private OpenLocalFileAction openAction; - private IFile file; + /* private */boolean shutdown = false; + //grouping on + private boolean groupingOn; - public boolean isValidInput(Object object) { - //don't volunteer to use this page unless forced to do so - return false; + //toggle constants for default click action + private boolean compareMode = false; + + protected LocalHistoryTableProvider historyTableProvider; + private RefreshFileHistory refreshFileHistoryJob; + private Composite localComposite; + private Action groupByDateMode; + private Action collapseAll; + private Action compareModeAction; + private CompareRevisionAction compareAction; + private OpenRevisionAction openAction; + + private HistoryResourceListener resourceListener; + + public boolean inputSet() { + currentFileRevision = null; + IFile tempFile = (IFile) getInput(); + this.file = tempFile; + if (tempFile == null) + return false; + + //blank current input only after we're sure that we have a file + //to fetch history for + this.treeViewer.setInput(null); + + localFileHistory = new LocalFileHistory(file); + + if (refreshFileHistoryJob == null) + refreshFileHistoryJob = new RefreshFileHistory(); + + //always refresh the history if the input gets set + refreshHistory(true); + return true; } - public void refresh() { - // TODO Auto-generated method stub - + private void refreshHistory(boolean refetch) { + if (refreshFileHistoryJob.getState() != Job.NONE){ + refreshFileHistoryJob.cancel(); + } + refreshFileHistoryJob.setFileHistory(localFileHistory); + refreshFileHistoryJob.setGrouping(groupingOn); + IHistoryPageSite parentSite = getHistoryPageSite(); + Utils.schedule(refreshFileHistoryJob, getWorkbenchSite(parentSite)); } - public String getName() { - // TODO Auto-generated method stub + private IWorkbenchPartSite getWorkbenchSite(IHistoryPageSite parentSite) { + IWorkbenchPart part = parentSite.getPart(); + if (part != null) + return part.getSite(); return null; } - + public void createControl(Composite parent) { - pgComp = new Composite(parent, SWT.NULL); - pgComp.setLayout(new FillLayout()); + + localComposite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + localComposite.setLayout(layout); + GridData data = new GridData(GridData.FILL_BOTH); + data.grabExcessVerticalSpace = true; + localComposite.setLayoutData(data); - tableViewer = createTable(pgComp); + treeViewer = createTree(localComposite); contributeActions(); + IHistoryPageSite parentSite = getHistoryPageSite(); + if (parentSite != null && parentSite instanceof DialogHistoryPageSite && treeViewer != null) + parentSite.setSelectionProvider(treeViewer); + + resourceListener = new HistoryResourceListener(); + ResourcesPlugin.getWorkspace().addResourceChangeListener(resourceListener, IResourceChangeEvent.POST_CHANGE); } private void contributeActions() { - // Double click open action - openAction = new OpenLocalFileAction(TeamUIMessages.LocalHistoryPage_openRevision); - tableViewer.getTable().addListener(SWT.DefaultSelection, new Listener() { - public void handleEvent(Event e) { - openAction.selectionChanged((IStructuredSelection) tableViewer.getSelection()); - openAction.run(); + final IPreferenceStore store = TeamUIPlugin.getPlugin().getPreferenceStore(); + //Group by Date + groupByDateMode = new Action(TeamUIMessages.LocalHistoryPage_GroupRevisionsByDateAction, TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_DATES_CATEGORY)){ + public void run() { + groupingOn = !groupingOn; + compareModeAction.setChecked(groupingOn); + store.setValue(IPreferenceIds.PREF_GROUPBYDATE_MODE, groupingOn); + refreshHistory(false); + } + }; + groupingOn = store.getBoolean(IPreferenceIds.PREF_GROUPBYDATE_MODE); + groupByDateMode.setChecked(groupingOn); + groupByDateMode.setToolTipText(TeamUIMessages.LocalHistoryPage_GroupRevisionsByDateTip); + groupByDateMode.setDisabledImageDescriptor(TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_DATES_CATEGORY)); + groupByDateMode.setHoverImageDescriptor(TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_DATES_CATEGORY)); + + //Collapse All + collapseAll = new Action(TeamUIMessages.LocalHistoryPage_CollapseAllAction, TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_COLLAPSE_ALL)) { + public void run() { + treeViewer.collapseAll(); + } + }; + collapseAll.setToolTipText(TeamUIMessages.LocalHistoryPage_CollapseAllTip); + collapseAll.setDisabledImageDescriptor(TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_COLLAPSE_ALL)); + collapseAll.setHoverImageDescriptor(TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_COLLAPSE_ALL)); + + //Compare Mode Action + compareModeAction = new Action(TeamUIMessages.LocalHistoryPage_CompareModeAction,TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_COMPARE_VIEW)) { + public void run() { + compareMode = !compareMode; + compareModeAction.setChecked(compareMode); + } + }; + compareModeAction.setToolTipText(TeamUIMessages.LocalHistoryPage_CompareModeTip); + compareModeAction.setDisabledImageDescriptor(TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_COMPARE_VIEW)); + compareModeAction.setHoverImageDescriptor(TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_COMPARE_VIEW)); + compareModeAction.setChecked(false); + + // Click Compare action + compareAction = new CompareRevisionAction(TeamUIMessages.LocalHistoryPage_CompareAction); + treeViewer.getTree().addSelectionListener(new SelectionAdapter(){ + public void widgetSelected(SelectionEvent e) { + compareAction.setCurrentFileRevision(getCurrentFileRevision()); + compareAction.selectionChanged((IStructuredSelection) treeViewer.getSelection()); + } + }); + compareAction.setPage(this); + + openAction = new OpenRevisionAction(TeamUIMessages.LocalHistoryPage_OpenAction); + treeViewer.getTree().addSelectionListener(new SelectionAdapter(){ + public void widgetSelected(SelectionEvent e) { + openAction.selectionChanged((IStructuredSelection) treeViewer.getSelection()); + } + }); + openAction.setPage(this); + + OpenStrategy handler = new OpenStrategy(treeViewer.getTree()); + handler.addOpenListener(new IOpenEventListener() { + public void handleOpen(SelectionEvent e) { + StructuredSelection tableStructuredSelection = (StructuredSelection) treeViewer.getSelection(); + if (compareMode){ + StructuredSelection sel = new StructuredSelection(new Object[] {getCurrentFileRevision(), tableStructuredSelection.getFirstElement()}); + compareAction.selectionChanged(sel); + compareAction.run(); + } else { + //Pass in the entire structured selection to allow for multiple editor openings + StructuredSelection sel = tableStructuredSelection; + openAction.selectionChanged(sel); + openAction.run(); + } } }); //Contribute actions to popup menu MenuManager menuMgr = new MenuManager(); - Menu menu = menuMgr.createContextMenu(tableViewer.getTable()); + Menu menu = menuMgr.createContextMenu(treeViewer.getTree()); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager menuMgr) { fillTableMenu(menuMgr); } }); menuMgr.setRemoveAllWhenShown(true); - tableViewer.getTable().setMenu(menu); - IWorkbenchPart part = getHistoryPageSite().getPart(); - if (part != null) { - IWorkbenchPartSite workbenchPartSite = part.getSite(); - workbenchPartSite.registerContextMenu(menuMgr, tableViewer); + 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(cvsHistoryFilter); + actionBarsMenu.add(toggleFilterAction); + } + actionBars.updateActionBars(); + } + }*/ + + //Create the local tool bar + IToolBarManager tbm = parentSite.getToolBarManager(); + if (tbm != null) { + //Add groups + tbm.add(new Separator("grouping")); //$NON-NLS-1$ + tbm.appendToGroup("grouping", groupByDateMode); //$NON-NLS-1$ + tbm.add(new Separator("modes")); //$NON-NLS-1$ + tbm.add(new Separator("collapse")); //$NON-NLS-1$ + tbm.appendToGroup("collapse", collapseAll); //$NON-NLS-1$ + tbm.appendToGroup("collapse", compareModeAction); //$NON-NLS-1$ + tbm.update(false); } + } - /* private */void fillTableMenu(IMenuManager menuMgr) { - IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); - openAction.selectionChanged(selection); - menuMgr.add(openAction); - /*compareAction.setEnabled(selection.size() == 2); - compareAction.selectionChanged(selection); - menuMgr.add(compareAction);*/ - menuMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + protected 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); + manager.add(compareAction); + } } - - private TableViewer createTable(Composite parent) { + + /** + * Creates the tree that displays the local file revisions + * + * @param the parent composite to contain the group + * @return the group control + */ + protected TreeViewer createTree(Composite parent) { + historyTableProvider = new LocalHistoryTableProvider(); - TableViewer viewer = historyTableProvider.createTable(parent); - - viewer.setContentProvider(new IStructuredContentProvider(){ + TreeViewer viewer = historyTableProvider.createTree(parent); + viewer.setContentProvider(new ITreeContentProvider() { public Object[] getElements(Object inputElement) { - //The entries of already been fetch so return them + + // 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]; - // The entries need to be fetch (or are being fetched) - if (!(inputElement instanceof IResource)) - return null; - - final IFile inputFile = (IFile) inputElement; - if (fetchLocalHistoryJob == null) { - fetchLocalHistoryJob = new FetchLocalHistoryJob(); + if (inputElement instanceof AbstractHistoryCategory[]){ + return (AbstractHistoryCategory[]) inputElement; } + + final IFileHistory fileHistory = (IFileHistory) inputElement; + entries = fileHistory.getFileRevisions(); + + return entries; + } - IFile file = fetchLocalHistoryJob.getFile(); - - if (file == null || !file.equals(inputFile)) { // The resource - // has changed - // so stop the - // currently - // running job - if (fetchLocalHistoryJob.getState() != Job.NONE) { - fetchLocalHistoryJob.cancel(); - try { - fetchLocalHistoryJob.join(); - } catch (InterruptedException e) { - TeamUIPlugin.log(new TeamException(NLS.bind(TeamUIMessages.GenericHistoryView_ErrorFetchingEntries, new String[] {""}), e)); //$NON-NLS-1$ - } - } - fetchLocalHistoryJob.setFile(inputFile); - } // Schedule the job even if it is already running - Utils.schedule(fetchLocalHistoryJob, getHistoryPageSite().getWorkbenchPageSite()); + public void dispose() { + } - return new Object[0]; + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + entries = null; } - public void dispose() { - // TODO Auto-generated method stub + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof AbstractHistoryCategory){ + return ((AbstractHistoryCategory) parentElement).getRevisions(); + } + return null; } - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // TODO Auto-generated method stub + public Object getParent(Object element) { + return null; + } + + public boolean hasChildren(Object element) { + if (element instanceof AbstractHistoryCategory){ + return ((AbstractHistoryCategory) element).hasRevisions(); + } + return false; } - }); - + return viewer; } public Control getControl() { - return pgComp; + return localComposite; } public void setFocus() { - pgComp.setFocus(); + localComposite.setFocus(); } - - private class FetchLocalHistoryJob extends Job { - public IFile localFile; - public FetchLocalHistoryJob() { - super(TeamUIMessages.LocalHistoryPage_fetchingLocalHistory); - } - - public IFile getFile() { - return localFile; - } + public String getDescription() { + if (file != null) + return file.getFullPath().toString(); + + return null; + } - public void setFile(IFile file) { - localFile = file; - } + public String getName() { + if (file != null) + return file.getName(); + + return ""; //$NON-NLS-1$ + } - public IStatus run(IProgressMonitor monitor) { - try { - if (localFile != null && !shutdown) { - entries = localFile.getHistory(monitor); - getSite().getShell().getDisplay().asyncExec(new Runnable() { - public void run() { - if (entries != null && tableViewer != null && !tableViewer.getTable().isDisposed()) { - tableViewer.refresh(); - } - } - }); - } - return Status.OK_STATUS; - } catch (CoreException e) { - return e.getStatus(); - } + public boolean isValidInput(Object object) { + //true if object is an unshared file + if (object instanceof IFile) { + if (!RepositoryProvider.isShared(((IFile) object).getProject())) + return true; } + + return false; + } + public void refresh() { + refreshHistory(true); } public Object getAdapter(Class adapter) { @@ -206,28 +372,195 @@ public class LocalHistoryPage extends HistoryPage { return null; } - public String getDescription() { - if (file != null) - return file.getFullPath().toString(); - return null; - } + public void dispose() { + shutdown = true; + + if (resourceListener != null){ + ResourcesPlugin.getWorkspace().removeResourceChangeListener(resourceListener); + resourceListener = null; + } + + //Cancel any incoming + if (refreshFileHistoryJob != null) { + if (refreshFileHistoryJob.getState() != Job.NONE) { + refreshFileHistoryJob.cancel(); + } + } + + + } + + public IFileRevision getCurrentFileRevision() { + if (currentFileRevision != null) + return currentFileRevision; - public Object getInput() { - return file; + if (file != null) + currentFileRevision = new LocalFileRevision(file); + + return currentFileRevision; } + + private class RefreshFileHistory extends Job { + private final static int NUMBER_OF_CATEGORIES = 4; + + private LocalFileHistory fileHistory; + private AbstractHistoryCategory[] categories; + private boolean grouping; + private Object[] elementsToExpand; + + public RefreshFileHistory() { + super(TeamUIMessages.LocalHistoryPage_FetchLocalHistoryMessage); + } + + public void setFileHistory(LocalFileHistory fileHistory) { + this.fileHistory = fileHistory; + } + + public void setGrouping (boolean value){ + this.grouping = value; + } - public boolean inputSet() { - Object object = getInput(); - if (object instanceof IFile) { - file = (IFile) object; - if ( object == null) - return false; + public IStatus run(IProgressMonitor monitor) { + + IStatus status = Status.OK_STATUS; + + if (fileHistory != null && !shutdown) { + //If fileHistory termintates in a bad way, try to fetch the local + //revisions only + try { + fileHistory.refresh(monitor); + } catch (CoreException ex) { + status = new TeamStatus(ex.getStatus().getSeverity(), TeamUIPlugin.ID, ex.getStatus().getCode(), ex.getMessage(), ex, file); + } + + if (grouping) + sortRevisions(); + + Utils.asyncExec(new Runnable() { + public void run() { + historyTableProvider.setFile(file); + if (grouping) { + mapExpandedElements(treeViewer.getExpandedElements()); + treeViewer.getTree().setRedraw(false); + 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.setInput(fileHistory); + } else { + categories = new AbstractHistoryCategory[] {getErrorMessage()}; + treeViewer.setInput(categories); + } + } + } + }, treeViewer); + } + + if (status != Status.OK_STATUS ) { + this.setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE); + this.setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE); + } + + return status; + } + + 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 = (Object[]) 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(TeamUIMessages.HistoryPage_Today, currentCal, null); + //Get yesterday + Calendar yesterdayCal = Calendar.getInstance(); + yesterdayCal.roll(Calendar.DAY_OF_YEAR, -1); + tempCategories[1] = new DateHistoryCategory(TeamUIMessages.HistoryPage_Yesterday, yesterdayCal, null); + //Get last week + Calendar lastWeekCal = Calendar.getInstance(); + lastWeekCal.roll(Calendar.DAY_OF_YEAR, -7); + tempCategories[2] = new DateHistoryCategory(TeamUIMessages.HistoryPage_LastWeek, lastWeekCal, yesterdayCal); + //Everything before after week is previous + tempCategories[3] = new DateHistoryCategory(TeamUIMessages.HistoryPage_Previous, null, lastWeekCal); + + 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; + } - //historyTableProvider.setFile(fileHistory, newfile); - tableViewer.setInput(file); - return true; + private MessageHistoryCategory getErrorMessage(){ + MessageHistoryCategory messageCategory = new MessageHistoryCategory(TeamUIMessages.LocalHistoryPage_NoRevisionsFound); + return messageCategory; } - return false; } - + + private class HistoryResourceListener implements IResourceChangeListener { + /** + * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent) + */ + public void resourceChanged(IResourceChangeEvent event) { + IResourceDelta root = event.getDelta(); + + if (file == null) + return; + + IResourceDelta resourceDelta = root.findMember(file.getFullPath()); + if (resourceDelta != null){ + Display.getDefault().asyncExec(new Runnable() { + public void run() { + refresh(); + } + }); + } + } + } + + } diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/LocalHistoryPageSource.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/LocalHistoryPageSource.java new file mode 100644 index 000000000..73567c257 --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/LocalHistoryPageSource.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.internal.ui.history; + +import org.eclipse.core.resources.IResource; +import org.eclipse.team.ui.history.HistoryPageSource; +import org.eclipse.ui.part.Page; + +public class LocalHistoryPageSource extends HistoryPageSource { + + public boolean canShowHistoryFor(Object object) { + return (object instanceof IResource && ((IResource) object).getType() == IResource.FILE); + } + + public Page createPage(Object object) { + LocalHistoryPage page = new LocalHistoryPage(); + return page; + } + +} diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/LocalHistoryTableProvider.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/LocalHistoryTableProvider.java index 7be83a309..a1e4b92fa 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/LocalHistoryTableProvider.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/LocalHistoryTableProvider.java @@ -13,37 +13,96 @@ package org.eclipse.team.internal.ui.history; import java.text.DateFormat; import java.util.Date; -import org.eclipse.core.resources.IFileState; +import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.*; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.*; -import org.eclipse.team.internal.ui.TeamUIMessages; +import org.eclipse.team.core.history.IFileRevision; +import org.eclipse.team.internal.core.history.LocalFileRevision; +import org.eclipse.team.internal.ui.*; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.themes.ITheme; public class LocalHistoryTableProvider { /** * The Local history label provider. */ class LocalHistoryLabelProvider extends LabelProvider implements ITableLabelProvider, IColorProvider, IFontProvider { + + Image dateImage = null; + ImageDescriptor dateDesc = null; + + Image localRevImage = null; + ImageDescriptor localRevDesc = null; + + ThemeListener themeListener; + + public LocalHistoryLabelProvider(LocalHistoryTableProvider provider){ + PlatformUI.getWorkbench().getThemeManager().addPropertyChangeListener(themeListener= new ThemeListener(provider)); + } + + public void dispose() { + if (dateImage != null){ + JFaceResources.getResources().destroyImage(dateDesc); + dateImage = null; + } + + if (localRevImage != null) { + JFaceResources.getResources().destroyImage(localRevDesc); + localRevImage = null; + } + + if (themeListener != null){ + PlatformUI.getWorkbench().getThemeManager().removePropertyChangeListener(themeListener); + } + } + public Image getColumnImage(Object element, int columnIndex) { + if (element instanceof DateHistoryCategory && columnIndex == COL_DATE) { + if (dateImage == null) { + dateDesc = TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_DATES_CATEGORY); + dateImage = dateDesc.createImage(); + return dateImage; + } + return dateImage; + } + + if (element instanceof LocalFileRevision && columnIndex == COL_DATE) { + if (localRevImage == null) { + localRevDesc = TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_LOCALREVISION_TABLE); + localRevImage = localRevDesc.createImage(); + return localRevDesc.createImage(); + } + return localRevImage; + } + return null; } public String getColumnText(Object element, int columnIndex) { - IFileState entry = adaptToFileState(element); + if (element instanceof AbstractHistoryCategory){ + if (columnIndex != COL_DATE) + return ""; //$NON-NLS-1$ + + return ((AbstractHistoryCategory) element).getName(); + } + + IFileRevision entry = adaptToFileRevision(element); if (entry == null) return ""; //$NON-NLS-1$ switch (columnIndex) { case COL_DATE : - String revision = DateFormat.getDateTimeInstance().format(new Date(entry.getModificationTime())); - return revision; - case COL_AUTHOR: - return ""; //$NON-NLS-1$ - - case COL_COMMENT: - return TeamUIMessages.LocalHistoryTableProvider_localRevision; + long date = entry.getTimestamp(); + Date dateFromLong = new Date(date); + return DateFormat.getInstance().format(dateFromLong); } return ""; //$NON-NLS-1$ } @@ -52,10 +111,15 @@ public class LocalHistoryTableProvider { * @see org.eclipse.jface.viewers.IColorProvider#getForeground(java.lang.Object) */ public Color getForeground(Object element) { - /*IFileState = adaptToFileState(element); - if (!entry.exists()) { - return Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW); - }*/ + if (element instanceof AbstractHistoryCategory){ + ITheme current = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme(); + return current.getColorRegistry().get("org.eclipse.team.cvs.ui.fontsandcolors.cvshistorypagecategories"); //$NON-NLS-1$ + } + + IFileRevision entry = adaptToFileRevision(element); + if (!entry.exists()) { + return Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW); + } return null; } @@ -72,106 +136,272 @@ public class LocalHistoryTableProvider { * @see org.eclipse.jface.viewers.IFontProvider#getFont(java.lang.Object) */ public Font getFont(Object element) { - IFileState entry = adaptToFileState(element); - if (entry == null) - return null; - /*String revision = entry.getContentIdentifier(); - String tempCurrentRevision = getCurrentRevision(); - if (tempCurrentRevision != null && tempCurrentRevision.equals(revision)) { - if (currentRevisionFont == null) { - Font defaultFont = JFaceResources.getDefaultFont(); - FontData[] data = defaultFont.getFontData(); - for (int i = 0; i < data.length; i++) { - data[i].setStyle(SWT.ITALIC); - } - currentRevisionFont = new Font(viewer.getTable().getDisplay(), data); - } - return currentRevisionFont; - }*/ + if (element instanceof AbstractHistoryCategory) { + return getCurrentRevisionFont(); + } + + IFileRevision entry = adaptToFileRevision(element); + if (entry == null) + return null; + long timestamp = entry.getTimestamp(); + long tempCurrentTimeStamp = getCurrentRevision(); + if (tempCurrentTimeStamp != 0 && tempCurrentTimeStamp==timestamp) { + return getCurrentRevisionFont(); + } return null; } - } - //column constants - private static final int COL_DATE = 0; - private static final int COL_AUTHOR = 1; - private static final int COL_COMMENT = 2; - - protected IFileState adaptToFileState(Object element) { - // Get the log entry for the provided object - IFileState entry = null; - if (element instanceof IFileState) { - entry = (IFileState) element; - } else if (element instanceof IAdaptable) { - entry = (IFileState) ((IAdaptable) element).getAdapter(IFileState.class); + private Font getCurrentRevisionFont() { + if (currentRevisionFont == null) { + Font defaultFont = JFaceResources.getDefaultFont(); + FontData[] data = defaultFont.getFontData(); + for (int i = 0; i < data.length; i++) { + data[i].setStyle(SWT.BOLD); + } + currentRevisionFont = new Font(viewer.getTree().getDisplay(), data); + } + return currentRevisionFont; } - return entry; } /** - * Create a TableViewer that can be used to display a list of IFileRevision instances. - * Ths method provides the labels and sorter but does not provide a content provider - * - * @param parent - * @return TableViewer + * The history sorter */ - public TableViewer createTable(Composite parent) { - Table table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION); - table.setHeaderVisible(true); - table.setLinesVisible(true); - GridData data = new GridData(GridData.FILL_BOTH); - table.setLayoutData(data); + class HistorySorter extends ViewerSorter { + private boolean reversed = false; + private int columnNumber; + + // column headings: "Revision" "Tags" "Date" "Author" "Comment" + private int[][] SORT_ORDERS_BY_COLUMN = { + {COL_DATE}, /* date */ + }; - TableLayout layout = new TableLayout(); - table.setLayout(layout); + /** + * The constructor. + * @param columnNumber + */ + public HistorySorter(int columnNumber) { + this.columnNumber = columnNumber; + } - TableViewer viewer = new TableViewer(table); + /** + * Compares two log entries, sorting first by the main column of this sorter, + * then by subsequent columns, depending on the column sort order. + */ + public int compare(Viewer compareViewer, Object o1, Object o2) { + /*if (o1 instanceof AbstractCVSHistoryCategory || o2 instanceof AbstractCVSHistoryCategory) + return 0;*/ + + IFileRevision e1 = adaptToFileRevision(o1); + IFileRevision e2 = adaptToFileRevision(o2); + int result = 0; + if (e1 == null || e2 == null) { + result = super.compare(compareViewer, o1, o2); + } else { + int[] columnSortOrder = SORT_ORDERS_BY_COLUMN[columnNumber]; + for (int i = 0; i < columnSortOrder.length; ++i) { + result = compareColumnValue(columnSortOrder[i], e1, e2); + if (result != 0) + break; + } + } + if (reversed) + result = -result; + return result; + } - createColumns(table, layout, viewer); + /** + * Compares two markers, based only on the value of the specified column. + */ + int compareColumnValue(int columnNumber, IFileRevision e1, IFileRevision e2) { + switch (columnNumber) { + case 0 : /* date */ + long date1 = e1.getTimestamp(); + long date2 = e2.getTimestamp(); + if (date1 == date2) + return 0; - viewer.setLabelProvider(new LocalHistoryLabelProvider()); + return date1 > date2 ? -1 : 1; + + default : + return 0; + } + } - // By default, reverse sort by revision. - //HistorySorter sorter = new HistorySorter(COL_REVISIONID); - //sorter.setReversed(true); - //viewer.setSorter(sorter); + /** + * Returns the number of the column by which this is sorting. + * @return the column number + */ + public int getColumnNumber() { + return columnNumber; + } - /* table.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - if (currentRevisionFont != null) { - currentRevisionFont.dispose(); - } - } - });*/ + /** + * Returns true for descending, or false + * for ascending sorting order. + * @return returns true if reversed + */ + public boolean isReversed() { + return reversed; + } - return viewer; + /** + * Sets the sorting order. + * @param newReversed + */ + public void setReversed(boolean newReversed) { + reversed = newReversed; + } + } + + /* private */ TreeViewer viewer; + /* private */Font currentRevisionFont; + + private IFile currentFile; + + //column constants + private static final int COL_DATE = 0; + + protected IFileRevision adaptToFileRevision(Object element) { + // Get the log entry for the provided object + IFileRevision entry = null; + if (element instanceof IFileRevision) { + entry = (IFileRevision) element; + } else if (element instanceof IAdaptable) { + entry = (IFileRevision) ((IAdaptable) element).getAdapter(IFileRevision.class); + } else if (element instanceof AbstractHistoryCategory){ + IFileRevision[] revisions = ((AbstractHistoryCategory) element).getRevisions(); + if (revisions.length > 0) + entry = revisions[0]; + } + return entry; } /** * Creates the columns for the history table. */ - private void createColumns(Table table, TableLayout layout, TableViewer viewer) { - //SelectionListener headerListener = getColumnListener(viewer); - + private void createColumns(Tree tree, TableLayout layout) { + SelectionListener headerListener = getColumnListener(viewer); // creation date - TableColumn col = new TableColumn(table, SWT.NONE); + TreeColumn col = new TreeColumn(tree, SWT.NONE); col.setResizable(true); col.setText(TeamUIMessages.GenericHistoryTableProvider_RevisionTime); - //col.addSelectionListener(headerListener); + col.addSelectionListener(headerListener); layout.addColumnData(new ColumnWeightData(20, true)); - // author - col = new TableColumn(table, SWT.NONE); + /*// author + col = new TreeColumn(tree, SWT.NONE); col.setResizable(true); col.setText(TeamUIMessages.GenericHistoryTableProvider_Author); - //col.addSelectionListener(headerListener); + col.addSelectionListener(headerListener); layout.addColumnData(new ColumnWeightData(20, true)); //comment - col = new TableColumn(table, SWT.NONE); + col = new TreeColumn(tree, SWT.NONE); col.setResizable(true); col.setText(TeamUIMessages.GenericHistoryTableProvider_Comment); - //col.addSelectionListener(headerListener); - layout.addColumnData(new ColumnWeightData(50, true)); + col.addSelectionListener(headerListener); + layout.addColumnData(new ColumnWeightData(50, true));*/ + } + + /** + * Adds the listener that sets the sorter. + */ + private SelectionListener getColumnListener(final TreeViewer treeViewer) { + /** + * This class handles selections of the column headers. + * Selection of the column header will cause resorting + * of the shown tasks using that column's sorter. + * Repeated selection of the header will toggle + * sorting order (ascending versus descending). + */ + return new SelectionAdapter() { + /** + * Handles the case of user selecting the + * header area. + * <p>If the column has not been selected previously, + * it will set the sorter of that column to be + * the current tasklist sorter. Repeated + * presses on the same column header will + * toggle sorting order (ascending/descending). + */ + public void widgetSelected(SelectionEvent e) { + // column selected - need to sort + int column = treeViewer.getTree().indexOf((TreeColumn) e.widget); + HistorySorter oldSorter = (HistorySorter) treeViewer.getSorter(); + if (oldSorter != null && column == oldSorter.getColumnNumber()) { + oldSorter.setReversed(!oldSorter.isReversed()); + treeViewer.refresh(); + } else { + treeViewer.setSorter(new HistorySorter(column)); + } + } + }; + } + + /** + * Create a TreeViewer that can be used to display a list of IFile instances. + * Ths method provides the labels and sorter but does not provide a content provider + * + * @param parent + * @return TableViewer + */ + public TreeViewer createTree(Composite parent) { + Tree tree = new Tree(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION); + tree.setHeaderVisible(true); + tree.setLinesVisible(false); + + GridData data = new GridData(GridData.FILL_BOTH); + tree.setLayoutData(data); + + TableLayout layout = new TableLayout(); + tree.setLayout(layout); + + this.viewer = new TreeViewer(tree); + + createColumns(tree, layout); + + viewer.setLabelProvider(new LocalHistoryLabelProvider(this)); + + // By default, reverse sort by revision. + // If local filter is on sort by date + HistorySorter sorter = new HistorySorter(COL_DATE); + sorter.setReversed(false); + viewer.setSorter(sorter); + + tree.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + if (currentRevisionFont != null) { + currentRevisionFont.dispose(); + } + } + }); + + return viewer; + } + + public void setFile(IFile file) { + this.currentFile = file; + } + + public long getCurrentRevision() { + + if (currentFile != null) { + return currentFile.getModificationStamp(); + } + + return 0; + } + + private static class ThemeListener implements IPropertyChangeListener { + + private final LocalHistoryTableProvider provider; + + ThemeListener(LocalHistoryTableProvider provider) { + this.provider= provider; + } + public void propertyChange(PropertyChangeEvent event) { + provider.viewer.refresh(); + } } } diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/MessageCVSHistoryCategory.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/MessageHistoryCategory.java index d14f1f0b2..e1d75af16 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/MessageCVSHistoryCategory.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/MessageHistoryCategory.java @@ -8,14 +8,14 @@ * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ -package org.eclipse.team.internal.ccvs.ui; +package org.eclipse.team.internal.ui.history; import org.eclipse.team.core.history.IFileRevision; -public class MessageCVSHistoryCategory extends AbstractCVSHistoryCategory { +public class MessageHistoryCategory extends AbstractHistoryCategory { private String message; - public MessageCVSHistoryCategory(String message){ + public MessageHistoryCategory(String message){ this.message = message; } public String getName() { @@ -27,7 +27,7 @@ public class MessageCVSHistoryCategory extends AbstractCVSHistoryCategory { } public IFileRevision[] getRevisions() { - return null; + return new IFileRevision[0]; } public boolean hasRevisions() { diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/ShowLocalHistory.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/ShowLocalHistory.java index 7fdcee190..45ce9e639 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/ShowLocalHistory.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/history/ShowLocalHistory.java @@ -43,7 +43,7 @@ public class ShowLocalHistory extends ActionDelegate implements IObjectActionDel IViewPart view = targetPart.getSite().getPage().showView("org.eclipse.team.ui.GenericHistoryView"); //$NON-NLS-1$ if (view instanceof GenericHistoryView){ GenericHistoryView historyView =(GenericHistoryView) view; - historyView.localItemDropped(resource); + historyView.itemDropped(resource,true); } } catch (PartInitException e) {}}}; diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties index b5377272f..c329c9e6f 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties @@ -397,7 +397,17 @@ TextAutoMerge_outputIOError= I/O error on writing TextAutoMerge_conflict= Conflict: cannot auto-merge LocalHistoryTableProvider_localRevision=<local revision> LocalHistoryPage_openRevision=Open Revision +LocalHistoryPage_CompareAction=&Compare +LocalHistoryPage_OpenAction=&Open LocalHistoryPage_fetchingLocalHistory=Fetching Local History +LocalHistoryPage_FetchLocalHistoryMessage=Fetching local history revisions +LocalHistoryPage_GroupRevisionsByDateAction=Group Revisions by Date +LocalHistoryPage_GroupRevisionsByDateTip=Group Revisions by Date +LocalHistoryPage_NoRevisionsFound=No revisions found +LocalHistoryPage_CollapseAllAction=Collapse All +LocalHistoryPage_CollapseAllTip=Collapse All +LocalHistoryPage_CompareModeAction=Compare Mode +LocalHistoryPage_CompareModeTip=Compare Mode CompareFileRevisionEditorInput_compareResourceAndVersions=Compare {0} {1} and {2} CompareFileRevisionEditorInput_repository=Repository file: {0} {1} @@ -433,3 +443,19 @@ MergeAllActionHandler_0=Merging all changes in {0} MergeAllActionHandler_1=Are you sure you want to merge {0} resources? MergeAllActionHandler_2=Are you sure you want to merge {0} resource? MergeAllActionHandler_3=Confirm Merge + +HistoryPage_Today=Today +HistoryPage_Yesterday=Yesterday +HistoryPage_LastWeek=Last Week +HistoryPage_Previous=Previous + +OpenRevisionAction_DeletedRevTitle=Deleted Revision +OpenRevisionAction_ErrorTitle=Open Revision +OpenRevisionAction_ErrorMessage=An error occurred while trying to open the revision. +OpenRevisionAction_DeletedRevMessage=This revision represents a deletion and cannot be opened. + +CompareRevisionAction_DeleteCompareMessage=One of the revisions represents a deletion and cannot be compared. +CompareRevisionAction_CompareWithCurrent=&Compare with Current Revision +CompareRevisionAction_CompareWithOther=&Compare with Each Other +CompareRevisionAction_Revision=Compare Current with {0} +CompareRevisionAction_Local=Compare Current with Local |