blob: 4ac48f61dfa8285205495c31bd56a953725d111e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.team.internal.ui.synchronize.actions;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import org.eclipse.compare.CompareEditorInput;
import org.eclipse.compare.CompareUI;
import org.eclipse.compare.structuremergeviewer.ICompareInput;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.team.core.synchronize.SyncInfo;
import org.eclipse.team.internal.ui.Utils;
import org.eclipse.team.internal.ui.mapping.ModelCompareEditorInput;
import org.eclipse.team.internal.ui.synchronize.SyncInfoModelElement;
import org.eclipse.team.internal.ui.synchronize.patch.ApplyPatchModelCompareEditorInput;
import org.eclipse.team.internal.ui.synchronize.patch.ApplyPatchSubscriberMergeContext;
import org.eclipse.team.ui.mapping.ISynchronizationCompareInput;
import org.eclipse.team.ui.mapping.ITeamContentProviderManager;
import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration;
import org.eclipse.team.ui.synchronize.ISynchronizePageSite;
import org.eclipse.team.ui.synchronize.ISynchronizeParticipant;
import org.eclipse.team.ui.synchronize.ModelSynchronizeParticipant;
import org.eclipse.team.ui.synchronize.SyncInfoCompareInput;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
/**
* Action to open a compare editor from a SyncInfo object.
*
* @see SyncInfoCompareInput
* @since 3.0
*/
public class OpenInCompareAction extends Action {
private final ISynchronizePageConfiguration configuration;
public OpenInCompareAction(ISynchronizePageConfiguration configuration) {
this.configuration = configuration;
Utils.initAction(this, "action.openInCompareEditor."); //$NON-NLS-1$
}
@Override
public void run() {
ISelection selection = configuration.getSite().getSelectionProvider().getSelection();
if(selection instanceof IStructuredSelection) {
if (!isOkToRun(selection))
return;
boolean reuseEditorIfPossible = ((IStructuredSelection) selection).size()==1;
for (Iterator iterator = ((IStructuredSelection) selection).iterator(); iterator.hasNext();) {
Object obj = iterator.next();
if (obj instanceof SyncInfoModelElement) {
SyncInfo info = ((SyncInfoModelElement) obj).getSyncInfo();
if (info != null) {
// Use the open strategy to decide if the editor or the sync view should have focus
openCompareEditorOnSyncInfo(configuration, info, !OpenStrategy.activateOnOpen(), reuseEditorIfPossible);
}
} else if (obj != null){
openCompareEditor(configuration, obj, !OpenStrategy.activateOnOpen(), reuseEditorIfPossible);
}
}
}
}
private boolean isOkToRun(ISelection selection) {
// do not open Compare Editor unless all elements have input
Object[] elements = ((IStructuredSelection) selection).toArray();
ISynchronizeParticipant participant = configuration
.getParticipant();
// model synchronize
if (participant instanceof ModelSynchronizeParticipant) {
ModelSynchronizeParticipant msp = (ModelSynchronizeParticipant) participant;
for (int i = 0; i < elements.length; i++) {
// TODO: This is inefficient
if (!msp.hasCompareInputFor(elements[i])) {
return false;
}
}
} else {
// all files
IResource resources[] = Utils.getResources(elements);
for (int i = 0; i < resources.length; i++) {
if (resources[i].getType() != IResource.FILE) {
// Only supported if all the items are files.
return false;
}
}
}
return true;
}
public static IEditorInput openCompareEditor(ISynchronizePageConfiguration configuration, Object object, boolean keepFocus, boolean reuseEditorIfPossible) {
Assert.isNotNull(object);
Assert.isNotNull(configuration);
ISynchronizeParticipant participant = configuration.getParticipant();
ISynchronizePageSite site = configuration.getSite();
if (object instanceof SyncInfoModelElement) {
SyncInfo info = ((SyncInfoModelElement) object).getSyncInfo();
if (info != null)
return openCompareEditorOnSyncInfo(configuration, info, keepFocus, reuseEditorIfPossible);
}
if (participant instanceof ModelSynchronizeParticipant) {
ModelSynchronizeParticipant msp = (ModelSynchronizeParticipant) participant;
ICompareInput input = msp.asCompareInput(object);
IWorkbenchPage workbenchPage = getWorkbenchPage(site);
if (input != null && workbenchPage != null && isOkToOpen(site, participant, input)) {
if (isApplyPatchModelPresent(configuration))
return openCompareEditor(workbenchPage, new ApplyPatchModelCompareEditorInput(msp, input, workbenchPage, configuration), keepFocus, site, reuseEditorIfPossible);
else
return openCompareEditor(workbenchPage, new ModelCompareEditorInput(msp, input, workbenchPage, configuration), keepFocus, site, reuseEditorIfPossible);
}
}
return null;
}
private static boolean isApplyPatchModelPresent(
ISynchronizePageConfiguration configuration) {
Object object = configuration.getProperty(ITeamContentProviderManager.P_SYNCHRONIZATION_CONTEXT);
return object instanceof ApplyPatchSubscriberMergeContext;
}
private static boolean isOkToOpen(final ISynchronizePageSite site, final ISynchronizeParticipant participant, final ICompareInput input) {
if (participant instanceof ModelSynchronizeParticipant && input instanceof ISynchronizationCompareInput) {
final ModelSynchronizeParticipant msp = (ModelSynchronizeParticipant) participant;
final boolean[] result = new boolean[] { false };
try {
PlatformUI.getWorkbench().getProgressService().run(true, true, monitor -> {
try {
result[0] = msp.checkForBufferChange(site.getShell(), (ISynchronizationCompareInput) input,
true, monitor);
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
});
} catch (InvocationTargetException e) {
Utils.handleError(site.getShell(), e, null, null);
} catch (InterruptedException e) {
return false;
}
return result[0];
}
return true;
}
public static CompareEditorInput openCompareEditorOnSyncInfo(ISynchronizePageConfiguration configuration, SyncInfo info, boolean keepFocus, boolean reuseEditorIfPossible) {
Assert.isNotNull(info);
Assert.isNotNull(configuration);
if(info.getLocal().getType() != IResource.FILE) return null;
SyncInfoCompareInput input = new SyncInfoCompareInput(configuration, info);
return openCompareEditor(getWorkbenchPage(configuration.getSite()), input, keepFocus, configuration.getSite(), reuseEditorIfPossible);
}
public static CompareEditorInput openCompareEditor(ISynchronizeParticipant participant, SyncInfo info, ISynchronizePageSite site) {
Assert.isNotNull(info);
Assert.isNotNull(participant);
if(info.getLocal().getType() != IResource.FILE) return null;
SyncInfoCompareInput input = new SyncInfoCompareInput(participant, info);
return openCompareEditor(getWorkbenchPage(site), input, false, site, false);
}
private static CompareEditorInput openCompareEditor(
IWorkbenchPage page,
CompareEditorInput input,
boolean keepFocus,
ISynchronizePageSite site,
boolean reuseEditorIfPossible) {
if (page == null)
return null;
openCompareEditor(input, page, reuseEditorIfPossible);
if(site != null && keepFocus) {
site.setFocus();
}
return input;
}
private static IWorkbenchPage getWorkbenchPage(ISynchronizePageSite site) {
IWorkbenchPage page = null;
if(site == null || site.getWorkbenchSite() == null) {
IWorkbenchWindow window= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (window != null)
page = window.getActivePage();
} else {
page = site.getWorkbenchSite().getPage();
}
return page;
}
public static void openCompareEditor(CompareEditorInput input, IWorkbenchPage page) {
// try to reuse editors, if possible
openCompareEditor(input, page, true);
}
public static void openCompareEditor(CompareEditorInput input, IWorkbenchPage page, boolean reuseEditorIfPossible) {
if (page == null || input == null)
return;
IEditorPart editor = Utils.findReusableCompareEditor(input, page,
new Class[] { SyncInfoCompareInput.class,
ModelCompareEditorInput.class });
// reuse editor only for single selection
if(editor != null && reuseEditorIfPossible) {
IEditorInput otherInput = editor.getEditorInput();
if(otherInput.equals(input)) {
// simply provide focus to editor
page.activate(editor);
} else {
// if editor is currently not open on that input either re-use existing
CompareUI.reuseCompareEditor(input, (IReusableEditor)editor);
page.activate(editor);
}
} else {
CompareUI.openCompareEditorOnPage(input, page);
}
}
/**
* Returns an editor handle if a SyncInfoCompareInput compare editor is opened on
* the given IResource.
*
* @param site the view site in which to search for editors
* @param resource the resource to use to find the compare editor
* @return an editor handle if found and <code>null</code> otherwise
*/
public static IEditorPart findOpenCompareEditor(IWorkbenchPartSite site, IResource resource) {
IWorkbenchPage page = site.getPage();
IEditorReference[] editorRefs = page.getEditorReferences();
for (int i = 0; i < editorRefs.length; i++) {
final IEditorPart part = editorRefs[i].getEditor(false /* don't restore editor */);
if(part != null) {
IEditorInput input = part.getEditorInput();
if(part != null && input instanceof SyncInfoCompareInput) {
SyncInfo inputInfo = ((SyncInfoCompareInput)input).getSyncInfo();
if(inputInfo.getLocal().equals(resource)) {
return part;
}
}
}
}
return null;
}
/**
* Returns an editor handle if a compare editor is opened on
* the given object.
* @param site the view site in which to search for editors
* @param object the object to use to find the compare editor
* @param participant
* @return an editor handle if found and <code>null</code> otherwise
*/
public static IEditorPart findOpenCompareEditor(IWorkbenchPartSite site, Object object, ISynchronizeParticipant participant) {
if (object instanceof SyncInfoModelElement) {
SyncInfoModelElement element = (SyncInfoModelElement) object;
SyncInfo info = element.getSyncInfo();
return findOpenCompareEditor(site, info.getLocal());
}
IWorkbenchPage page = site.getPage();
IEditorReference[] editorRefs = page.getEditorReferences();
for (int i = 0; i < editorRefs.length; i++) {
final IEditorPart part = editorRefs[i].getEditor(false /* don't restore editor */);
if(part != null) {
IEditorInput input = part.getEditorInput();
if(input instanceof ModelCompareEditorInput) {
if(((ModelCompareEditorInput)input).matches(object, participant)) {
return part;
}
}
}
}
return null;
}
}