### Eclipse Workspace Patch 1.0
#P org.eclipse.team.ui
Index: plugin.properties
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.team.ui/plugin.properties,v
retrieving revision 1.75
diff -u -r1.75 plugin.properties
--- plugin.properties 3 Jun 2008 13:35:37 -0000 1.75
+++ plugin.properties 27 Nov 2008 11:33:56 -0000
@@ -74,5 +74,7 @@
CompareLocalHistory.tooltip= Compare the Selected Resource with Local History
ReplaceLocalHistory.label= &Local History...
ReplaceLocalHistory.tooltip= Replace the Selected Resource with Local History
+CompareWithEachOtherAction.label= &Each Other
+CompareWithEachOtherAction.tooltip= Compare the Selected Resources
ignoresTransferName= Team Ignored Resources Transfer
Index: plugin.xml
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.team.ui/plugin.xml,v
retrieving revision 1.196
diff -u -r1.196 plugin.xml
--- plugin.xml 17 Apr 2008 15:31:56 -0000 1.196
+++ plugin.xml 27 Nov 2008 11:33:56 -0000
@@ -154,6 +154,15 @@
enablesFor="1"
overrideActionId="replaceFromHistory"
tooltip="%ReplaceLocalHistory.tooltip"/>
+
+
true if the editor was closed (note that the close
+ * may be asynchronous)
+ */
+ protected boolean closeEditor(boolean checkForUnsavedChanges) {
+ if (isSaveNeeded() && checkForUnsavedChanges) {
+ return false;
+ } else {
+ Runnable runnable = new Runnable() {
+ public void run() {
+ IEditorPart part = getPage().findEditor(
+ SaveablesCompareEditorInput.this);
+ getPage().closeEditor(part, false);
+ }
+ };
+ if (Display.getCurrent() != null) {
+ runnable.run();
+ } else {
+ Display display = getPage().getWorkbenchWindow().getShell()
+ .getDisplay();
+ display.asyncExec(runnable);
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Prepare the compare input of this editor input. This method is not
+ * intended to be overridden of extended by subclasses (but is not final for
+ * backwards compatibility reasons). The implementation of this method in
+ * this class delegates the creation of the compare input to the
+ * {@link #prepareCompareInput(IProgressMonitor)} method which subclasses
+ * must implement.
+ *
+ * @see org.eclipse.compare.CompareEditorInput#prepareInput(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected Object prepareInput(IProgressMonitor monitor)
+ throws InvocationTargetException, InterruptedException {
+ final ICompareInput input = prepareCompareInput(monitor);
+ if (input != null)
+ setTitle(NLS.bind(TeamUIMessages.SyncInfoCompareInput_title,
+ new String[] { input.getName() }));
+ return input;
+ }
+
+ /**
+ * Method called from {@link #prepareInput(IProgressMonitor)} to obtain the
+ * input. It's purpose is to ensure that the input is an instance of
+ * {@link ICompareInput}.
+ *
+ * @param monitor
+ * a progress monitor
+ * @return the compare input
+ * @throws InvocationTargetException
+ * @throws InterruptedException
+ */
+ protected ICompareInput prepareCompareInput(IProgressMonitor monitor)
+ throws InvocationTargetException, InterruptedException {
+ ICompareInput input = createCompareInput();
+ getCompareConfiguration().setLeftEditable(isEditable(input.getLeft()));
+ getCompareConfiguration()
+ .setRightEditable(isEditable(input.getRight()));
+ initLabels();
+ return input;
+ }
+
+ private boolean isEditable(Object obj) {
+ if (obj instanceof IEditableContent) {
+ return ((IEditableContent) obj).isEditable();
+ }
+ return false;
+ }
+
+ private void initLabels() {
+ CompareConfiguration cc = getCompareConfiguration();
+
+ IResource ancestorResource = getResource(fAncestorElement);
+ IResource leftResource = getResource(fLeftElement);
+ IResource rightResource = getResource(fRightElement);
+
+ if (ancestorResource != null) {
+ String ancestorLabel = ancestorResource.getFullPath()
+ .makeRelative().toString();
+
+ cc.setAncestorLabel(ancestorLabel);
+ }
+
+ if (leftResource != null && rightResource != null) {
+ String leftLabel = leftResource.getFullPath().makeRelative()
+ .toString();
+ String rightLabel = rightResource.getFullPath().makeRelative()
+ .toString();
+
+ cc.setLeftLabel(leftLabel);
+ cc.setRightLabel(rightLabel);
+ }
+ }
+
+ private ICompareInput createCompareInput() {
+ return fAncestorElement == null ? new MyDiffNode(fLeftElement,
+ fRightElement) : new MyDiffNode(fAncestorElement, fLeftElement,
+ fRightElement);
+ }
+
+ private CompareInputChangeNotifier notifier = new CompareInputChangeNotifier() {
+ protected IResource[] getResources(ICompareInput input) {
+ IResource leftResource = getResource(fLeftElement);
+ IResource rightResource = getResource(fRightElement);
+ if (leftResource == null && rightResource == null)
+ return new IResource[0];
+ if (leftResource == null && rightResource != null)
+ return new IResource[] { rightResource };
+ if (leftResource != null && rightResource == null)
+ return new IResource[] { leftResource };
+ return new IResource[] { leftResource, rightResource };
+ }
+ };
+
+ private class MyDiffNode extends AbstractCompareInput {
+ public MyDiffNode(ITypedElement left, ITypedElement right) {
+ super(Differencer.CHANGE, null, left, right);
+ }
+
+ public MyDiffNode(ITypedElement ancestor, ITypedElement left,
+ ITypedElement right) {
+ super(Differencer.CONFLICTING, ancestor, left, right);
+ }
+
+ public void fireChange() {
+ super.fireChange();
+ }
+
+ protected CompareInputChangeNotifier getChangeNotifier() {
+ return notifier;
+ }
+
+ public boolean needsUpdate() {
+ return true;
+ }
+
+ public void update() {
+ fireChange();
+ }
+ }
+
+ private IResource getResource(ITypedElement pElement) {
+ if (pElement instanceof LocalResourceTypedElement
+ && pElement instanceof IResourceProvider) {
+ return ((IResourceProvider) pElement).getResource();
+ }
+ return null;
+ }
+
+ public void registerContextMenu(final MenuManager pMenuManager,
+ final ISelectionProvider pSelectionProvider) {
+ super.registerContextMenu(pMenuManager, pSelectionProvider);
+ final Saveable lLeftSaveable = getLeftSaveable();
+ final ITypedElement lLeftElement = getFileElement(getCompareInput()
+ .getLeft(), this);
+ if (lLeftSaveable instanceof LocalResourceSaveableComparison) {
+ pMenuManager.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ handleMenuAboutToShow(manager, lLeftSaveable, lLeftElement,
+ pSelectionProvider);
+ }
+ });
+ }
+ final Saveable lRightSaveable = getRightSaveable();
+ final ITypedElement lRightElement = getFileElement(getCompareInput()
+ .getRight(), this);
+ if (lRightSaveable instanceof LocalResourceSaveableComparison) {
+ pMenuManager.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ handleMenuAboutToShow(manager, lRightSaveable,
+ lRightElement, pSelectionProvider);
+ }
+ });
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.compare.CompareEditorInput#addCompareInputChangeListener(
+ * org.eclipse.compare.structuremergeviewer.ICompareInput,
+ * org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener)
+ */
+ public void addCompareInputChangeListener(ICompareInput input,
+ ICompareInputChangeListener listener) {
+ if (input == getCompareResult()) {
+ inputChangeListeners.add(listener);
+ } else {
+ super.addCompareInputChangeListener(input, listener);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.compare.CompareEditorInput#removeCompareInputChangeListener
+ * (org.eclipse.compare.structuremergeviewer.ICompareInput,
+ * org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener)
+ */
+ public void removeCompareInputChangeListener(ICompareInput input,
+ ICompareInputChangeListener listener) {
+ if (input == getCompareResult()) {
+ inputChangeListeners.remove(listener);
+ } else {
+ super.removeCompareInputChangeListener(input, listener);
+ }
+ }
+
+ private void propogateInputChange() {
+ if (!inputChangeListeners.isEmpty()) {
+ Object[] allListeners = inputChangeListeners.getListeners();
+ final ICompareInput compareResult = (ICompareInput) getCompareResult();
+ for (int i = 0; i < allListeners.length; i++) {
+ final ICompareInputChangeListener listener = (ICompareInputChangeListener) allListeners[i];
+ SafeRunner.run(new ISafeRunnable() {
+ public void run() throws Exception {
+ listener.compareInputChanged(compareResult);
+ }
+
+ public void handleException(Throwable exception) {
+ // Logged by the safe runner
+ }
+ });
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.compare.CompareEditorInput#getTitleImage()
+ */
+ public Image getTitleImage() {
+ ImageRegistry reg = TeamUIPlugin.getPlugin().getImageRegistry();
+ Image image = reg.get(ITeamUIImages.IMG_SYNC_VIEW);
+ if (image == null) {
+ image = getImageDescriptor().createImage();
+ reg.put(ITeamUIImages.IMG_SYNC_VIEW, image);
+ }
+ return image;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IEditorInput#getImageDescriptor()
+ */
+ public ImageDescriptor getImageDescriptor() {
+ return TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_SYNC_VIEW);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.compare.CompareEditorInput#canRunAsJob()
+ */
+ public boolean canRunAsJob() {
+ return true;
+ }
+
+ private void handleMenuAboutToShow(IMenuManager manager, Saveable saveable,
+ ITypedElement element, ISelectionProvider provider) {
+ if (provider instanceof ITextViewer) {
+ ITextViewer v = (ITextViewer) provider;
+ IDocument d = v.getDocument();
+ IDocument other = (IDocument) Utils.getAdapter(saveable,
+ IDocument.class);
+ if (d == other) {
+ if (element instanceof IResourceProvider) {
+ IResourceProvider rp = (IResourceProvider) element;
+ IResource resource = rp.getResource();
+ StructuredSelection selection = new StructuredSelection(
+ resource);
+ IWorkbenchPart workbenchPart = getContainer()
+ .getWorkbenchPart();
+ if (workbenchPart != null) {
+ IWorkbenchSite ws = workbenchPart.getSite();
+ MenuManager submenu1 = new MenuManager(
+ getShowInMenuLabel());
+ IContributionItem showInMenu = ContributionItemFactory.VIEWS_SHOW_IN
+ .create(ws.getWorkbenchWindow());
+ submenu1.add(showInMenu);
+ manager.insertAfter("file", submenu1); //$NON-NLS-1$
+ MenuManager submenu2 = new MenuManager(
+ TeamUIMessages.OpenWithActionGroup_0);
+ submenu2.add(new OpenWithMenu(ws.getPage(), resource));
+ manager.insertAfter("file", submenu2); //$NON-NLS-1$
+
+ OpenFileAction openFileAction = new OpenFileAction(ws
+ .getPage());
+ openFileAction.selectionChanged(selection);
+ manager.insertAfter("file", openFileAction); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+
+ private String getShowInMenuLabel() {
+ String keyBinding = null;
+
+ IBindingService bindingService = (IBindingService) PlatformUI
+ .getWorkbench().getAdapter(IBindingService.class);
+ if (bindingService != null)
+ keyBinding = bindingService
+ .getBestActiveBindingFormattedFor("org.eclipse.ui.navigate.showInQuickMenu"); //$NON-NLS-1$
+
+ if (keyBinding == null)
+ keyBinding = ""; //$NON-NLS-1$
+
+ return NLS
+ .bind(TeamUIMessages.SaveableCompareEditorInput_0, keyBinding);
+ }
+
+ // TODO: add getAdapter for IFile[]
+
+ private class InternalResourceSaveableComparison extends
+ LocalResourceSaveableComparison implements
+ ISharedDocumentAdapterListener {
+ private LocalResourceTypedElement lrte;
+ private boolean connected = false;
+
+ public InternalResourceSaveableComparison(ICompareInput input,
+ CompareEditorInput editorInput, ITypedElement element) {
+ super(input, editorInput, element);
+ if (element instanceof LocalResourceTypedElement) {
+ lrte = (LocalResourceTypedElement) element;
+ if (lrte.isConnected()) {
+ registerSaveable(true);
+ } else {
+ lrte.setSharedDocumentListener(this);
+ }
+ }
+ }
+
+ protected void fireInputChange() {
+ SaveablesCompareEditorInput.this.fireInputChange();
+ }
+
+ public void dispose() {
+ super.dispose();
+ if (lrte != null)
+ lrte.setSharedDocumentListener(null);
+ }
+
+ public void handleDocumentConnected() {
+ if (connected)
+ return;
+ connected = true;
+ registerSaveable(false);
+ if (lrte != null)
+ lrte.setSharedDocumentListener(null);
+ }
+
+ private void registerSaveable(boolean init) {
+ ICompareContainer container = getContainer();
+ IWorkbenchPart part = container.getWorkbenchPart();
+ if (part != null) {
+ ISaveablesLifecycleListener lifecycleListener = getSaveablesLifecycleListener(part);
+ // Remove this saveable from the lifecycle listener
+ if (!init)
+ lifecycleListener
+ .handleLifecycleEvent(new SaveablesLifecycleEvent(
+ part, SaveablesLifecycleEvent.POST_CLOSE,
+ new Saveable[] { this }, false));
+ // Now fix the hashing so it uses the connected document
+ initializeHashing();
+ // Finally, add this saveable back to the listener
+ lifecycleListener
+ .handleLifecycleEvent(new SaveablesLifecycleEvent(part,
+ SaveablesLifecycleEvent.POST_OPEN,
+ new Saveable[] { this }, false));
+ }
+ }
+
+ public void handleDocumentDeleted() {
+ // Ignore
+ }
+
+ public void handleDocumentDisconnected() {
+ // Ignore
+ }
+
+ public void handleDocumentFlushed() {
+ // Ignore
+ }
+
+ public void handleDocumentSaved() {
+ // Ignore
+ }
+
+ /*
+ * @see org.eclipse.ui.Saveable#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+
+ if (!(obj instanceof Saveable))
+ return false;
+
+ if (document != null) {
+ Object otherDocument = ((Saveable) obj)
+ .getAdapter(IDocument.class);
+
+ if (document == null && otherDocument == null)
+ return false;
+
+ return document != null && document.equals(otherDocument);
+ }
+
+ if (obj instanceof InternalResourceSaveableComparison) {
+ InternalResourceSaveableComparison rscm = (InternalResourceSaveableComparison) obj;
+ return rscm.input.equals(input) && rscm.lrte.equals(lrte);
+ }
+ return false;
+ }
+ }
+}
Index: src/org/eclipse/team/internal/ui/actions/CompareAction.java
===================================================================
RCS file: src/org/eclipse/team/internal/ui/actions/CompareAction.java
diff -N src/org/eclipse/team/internal/ui/actions/CompareAction.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/team/internal/ui/actions/CompareAction.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.actions;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.compare.*;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.team.internal.ui.TeamUIMessages;
+import org.eclipse.team.internal.ui.synchronize.SaveablesCompareEditorInput;
+import org.eclipse.ui.*;
+
+public class CompareAction extends TeamAction {
+
+ protected void execute(IAction action) throws InvocationTargetException,
+ InterruptedException {
+
+ IResource[] selectedResources = getSelectedResources();
+
+ ITypedElement ancestor = null;
+ ITypedElement left = null;
+ ITypedElement right = null;
+
+ if (selectedResources.length == 2) {
+ if (selectedResources[0] != null)
+ left = getElementFor(selectedResources[0]);
+
+ if (selectedResources[1] != null)
+ right = getElementFor(selectedResources[1]);
+
+ } else if (selectedResources.length == 3) {
+ // prompt for ancestor
+ SelectAncestorDialog dialog = new SelectAncestorDialog(getShell(),
+ selectedResources);
+ int code = dialog.open();
+ if (code == Window.CANCEL)
+ return;
+
+ ancestor = getElementFor(dialog.ancestorResource);
+ left = getElementFor(dialog.leftResource);
+ right = getElementFor(dialog.rightResource);
+ } else {
+ return;
+ }
+ openInCompare(ancestor, left, right);
+ }
+
+ // XXX: from CompareRevisionAction*
+ private void openInCompare(ITypedElement ancestor, ITypedElement left,
+ ITypedElement right) {
+ IWorkbenchPage workBenchPage = getTargetPage();
+ CompareEditorInput input = new SaveablesCompareEditorInput(ancestor,
+ left, right, workBenchPage);
+ IEditorPart editor = CompareRevisionAction.findReusableCompareEditor(
+ input, workBenchPage);
+ if (editor != null) {
+ IEditorInput otherInput = editor.getEditorInput();
+ if (otherInput.equals(input)) {
+ // simply provide focus to editor
+ workBenchPage.activate(editor);
+ } else {
+ // if editor is currently not open on that input either re-use
+ // existing
+ CompareUI.reuseCompareEditor(input, (IReusableEditor) editor);
+ workBenchPage.activate(editor);
+ }
+ } else {
+ CompareUI.openCompareEditor(input);
+ }
+ }
+
+ public boolean isEnabled() {
+ int l = getSelectedResources().length;
+ return l == 2 || l == 3;
+ }
+
+ // XXX: from CompareRevisionAction
+ private ITypedElement getElementFor(IResource resource) {
+ return SaveablesCompareEditorInput.createFileElement((IFile) resource);
+ }
+
+ // see
+ // org.eclipse.compare.internal.ResourceCompareInput.SelectAncestorDialog
+ private class SelectAncestorDialog extends MessageDialog {
+ private IResource[] theResources;
+ IResource ancestorResource;
+ IResource leftResource;
+ IResource rightResource;
+
+ private Button[] buttons;
+
+ public SelectAncestorDialog(Shell parentShell, IResource[] theResources) {
+ super(parentShell, TeamUIMessages.SelectAncestorDialog_title, null,
+ TeamUIMessages.SelectAncestorDialog_message,
+ MessageDialog.QUESTION, new String[] {
+ IDialogConstants.OK_LABEL,
+ IDialogConstants.CANCEL_LABEL }, 0);
+ this.theResources = theResources;
+ }
+
+ protected Control createCustomArea(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout());
+ buttons = new Button[3];
+ for (int i = 0; i < 3; i++) {
+ buttons[i] = new Button(composite, SWT.RADIO);
+ buttons[i].addSelectionListener(selectionListener);
+ buttons[i].setText(NLS.bind(
+ TeamUIMessages.SelectAncestorDialog_option,
+ theResources[i].getFullPath().toPortableString()));
+ buttons[i].setFont(parent.getFont());
+ // set initial state
+ buttons[i].setSelection(i == 0);
+ }
+ pickAncestor(0);
+ return composite;
+ }
+
+ private void pickAncestor(int i) {
+ ancestorResource = theResources[i];
+ leftResource = theResources[i == 0 ? 1 : 0];
+ rightResource = theResources[i == 2 ? 1 : 2];
+ }
+
+ private SelectionListener selectionListener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ Button selectedButton = (Button) e.widget;
+ if (!selectedButton.getSelection())
+ return;
+ for (int i = 0; i < 3; i++)
+ if (selectedButton == buttons[i])
+ pickAncestor(i);
+ }
+ };
+ }
+
+}