Make left pane old version and right new in compare editor
[egit.git] / org.spearce.egit.ui / src / org / spearce / egit / ui / internal / actions / GitCompareRevisionAction.java
blobbc1e7348b2b73dfa969e4dee52c192ae336e2344
1 /*******************************************************************************
2 * Copyright (c) 2006 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Robin Rosenberg - Git interface
11 *******************************************************************************/
12 package org.spearce.egit.ui.internal.actions;
14 import org.eclipse.compare.CompareEditorInput;
15 import org.eclipse.compare.CompareUI;
16 import org.eclipse.compare.ITypedElement;
17 import org.eclipse.core.resources.IResource;
18 import org.eclipse.jface.dialogs.MessageDialog;
19 import org.eclipse.jface.viewers.IStructuredSelection;
20 import org.eclipse.osgi.util.NLS;
21 import org.eclipse.team.core.history.IFileRevision;
22 import org.eclipse.team.core.history.provider.FileRevision;
23 import org.eclipse.team.internal.core.history.LocalFileRevision;
24 import org.eclipse.team.internal.ui.TeamUIMessages;
25 import org.eclipse.team.internal.ui.history.AbstractHistoryCategory;
26 import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
27 import org.eclipse.team.ui.history.HistoryPage;
28 import org.eclipse.ui.IEditorInput;
29 import org.eclipse.ui.IEditorPart;
30 import org.eclipse.ui.IEditorReference;
31 import org.eclipse.ui.IReusableEditor;
32 import org.eclipse.ui.IWorkbenchPage;
33 import org.eclipse.ui.actions.BaseSelectionListenerAction;
34 import org.spearce.egit.core.GitWorkspaceFileRevision;
35 import org.spearce.egit.core.internal.mapping.GitFileRevision;
36 import org.spearce.egit.ui.internal.GitCompareFileRevisionEditorInput;
37 import org.spearce.egit.ui.internal.GitResourceNode;
38 import org.spearce.jgit.lib.ObjectId;
40 /**
41 * Action to invoke a Git based compare on selected revivsions in the history window.
43 * This class i almost a verbatim copy of @{link org.eclipse.team.internal.ui.actions.CompareRevisionAction}
44 * since it could not be subclassed to invoke the EGit methods.
46 public class GitCompareRevisionAction extends BaseSelectionListenerAction {
48 HistoryPage page;
49 IStructuredSelection selection;
50 IFileRevision currentFileRevision;
52 public GitCompareRevisionAction(String text) {
53 super(text);
56 public GitCompareRevisionAction() {
57 this(TeamUIMessages.LocalHistoryPage_CompareAction);
60 public void run() {
61 IStructuredSelection structSel = selection;
62 Object[] objArray = structSel.toArray();
64 IFileRevision file1 = null;
65 IFileRevision file2 = null;
67 switch (structSel.size()){
68 case 1:
69 file1 = getCurrentFileRevision();
70 Object tempRevision = objArray[0];
71 if (tempRevision instanceof IFileRevision)
72 file2 = (IFileRevision) tempRevision;
73 else
74 return;
75 break;
77 case 2:
78 Object tempRevision2 = objArray[0];
79 Object tempRevision3 = objArray[1];
81 if (tempRevision2 instanceof IFileRevision &&
82 tempRevision3 instanceof IFileRevision){
83 file1 = (IFileRevision) objArray[0];
84 file2 = (IFileRevision) objArray[1];
85 } else
86 return;
87 break;
90 if (file1 == null || file2 == null ||
91 !file1.exists() || !file2.exists()){
92 MessageDialog.openError(page.getSite().getShell(),
93 TeamUIMessages.OpenRevisionAction_DeletedRevTitle,
94 TeamUIMessages.CompareRevisionAction_DeleteCompareMessage);
95 return;
98 IResource resource = getResource(file2);
99 if (resource != null) {
100 IFileRevision temp = file1;
101 file1 = file2;
102 file2 = temp;
104 ITypedElement right;
105 resource = getResource(file1);
106 if (resource != null) {
107 right = new LocalResourceTypedElement(resource);
108 } else {
109 right = new GitResourceNode(file1);
111 ITypedElement left = new GitResourceNode(file2);
113 openInCompare(left, right);
116 private void openInCompare(ITypedElement left, ITypedElement right) {
117 CompareEditorInput input = createCompareEditorInput(left, right, page.getSite().getPage());
118 IWorkbenchPage workBenchPage = page.getSite().getPage();
119 IEditorPart editor = findReusableCompareEditor(workBenchPage);
120 if (editor != null) {
121 IEditorInput otherInput = editor.getEditorInput();
122 if (otherInput.equals(input)) {
123 // simply provide focus to editor
124 workBenchPage.activate(editor);
125 } else {
126 // if editor is currently not open on that input either re-use
127 // existing
128 CompareUI.reuseCompareEditor(input, (IReusableEditor) editor);
129 workBenchPage.activate(editor);
131 } else {
132 CompareUI.openCompareEditor(input);
136 protected GitCompareFileRevisionEditorInput createCompareEditorInput(
137 ITypedElement left, ITypedElement right, IWorkbenchPage page) {
138 return new GitCompareFileRevisionEditorInput(left, right, page);
141 private IResource getResource(IFileRevision revision) {
142 if (revision instanceof GitWorkspaceFileRevision) {
143 GitWorkspaceFileRevision local = (GitWorkspaceFileRevision) revision;
144 return local.getResource();
146 return null;
149 private IFileRevision getCurrentFileRevision() {
150 return currentFileRevision;
153 public void setCurrentFileRevision(IFileRevision fileRevision){
154 this.currentFileRevision = fileRevision;
158 * Returns an editor that can be re-used. An open compare editor that
159 * has un-saved changes cannot be re-used.
160 * @param page
161 * @return an EditorPart or <code>null</code> if none can be found
163 public static IEditorPart findReusableCompareEditor(IWorkbenchPage page) {
164 IEditorReference[] editorRefs = page.getEditorReferences();
165 for (int i = 0; i < editorRefs.length; i++) {
166 IEditorPart part = editorRefs[i].getEditor(false);
167 if(part != null
168 && (part.getEditorInput() instanceof GitCompareFileRevisionEditorInput)
169 && part instanceof IReusableEditor) {
170 if(! part.isDirty()) {
171 return part;
175 return null;
178 protected boolean updateSelection(IStructuredSelection selection) {
179 this.selection = selection;
180 if (selection.size() == 1){
181 Object el = selection.getFirstElement();
182 if (el instanceof LocalFileRevision)
183 this.setText(TeamUIMessages.CompareRevisionAction_Local);
184 else if (el instanceof FileRevision){
185 FileRevision tempFileRevision = (FileRevision) el;
186 this.setText(NLS.bind(TeamUIMessages.CompareRevisionAction_Revision, new String[]{tempFileRevision.getContentIdentifier()}));
188 else
189 this.setText(TeamUIMessages.CompareRevisionAction_CompareWithCurrent);
190 return shouldShow();
192 else if (selection.size() == 2){
193 IFileRevision rev1=(IFileRevision)selection.toArray()[0];
194 IFileRevision rev2=(IFileRevision)selection.toArray()[1];
195 System.out.println("Compare "+rev1.getContentIdentifier()+" with "+rev2.getContentIdentifier());
196 if (rev1 instanceof GitFileRevision && rev2 instanceof GitFileRevision) {
197 ObjectId pid = ((GitFileRevision)rev1).getCommit().getParentIds()[0];
198 if (pid.equals(((GitFileRevision)rev2).getCommit().getCommitId())) {
199 this.setText("Show commit diff");
200 } else {
201 this.setText(TeamUIMessages.CompareRevisionAction_CompareWithOther);
203 } else
204 this.setText(TeamUIMessages.CompareRevisionAction_CompareWithOther);
205 return shouldShow();
208 return false;
211 public void setPage(HistoryPage page) {
212 this.page = page;
215 private boolean shouldShow() {
216 IStructuredSelection structSel = selection;
217 Object[] objArray = structSel.toArray();
219 if (objArray.length == 0)
220 return false;
222 // Comparing the workspace revision with itself is just stupid
223 if (objArray.length == 1 && objArray[0] instanceof GitWorkspaceFileRevision)
224 return false;
226 for (int i = 0; i < objArray.length; i++) {
228 // Don't bother showing if this a category
229 if (objArray[i] instanceof AbstractHistoryCategory)
230 return false;
232 IFileRevision revision = (IFileRevision) objArray[i];
233 //check to see if any of the selected revisions are deleted revisions
234 if (revision != null && !revision.exists())
235 return false;
238 return true;