blob: f0363eb58befe6ef05e522eae62d99a1a87bb407 [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2008-2015 See4sys, itemis 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:
* See4sys - Initial API and implementation
* itemis - [457704] Integrate EMF compare 3.x in Sphinx
*
* </copyright>
*/
package org.eclipse.sphinx.emf.compare.ui.editor;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.compare.internal.CompareEditor;
import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.provider.AdapterFactoryItemDelegator;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.sphinx.emf.compare.ui.internal.Activator;
import org.eclipse.sphinx.emf.compare.ui.internal.messages.Messages;
import org.eclipse.sphinx.emf.editors.DefaultModelEditorInputChangeHandler;
import org.eclipse.sphinx.emf.editors.IModelEditorInputChangeAnalyzer;
import org.eclipse.sphinx.emf.editors.ModelEditorInputSynchronizer;
import org.eclipse.sphinx.emf.editors.ModelEditorUndoContextManager;
import org.eclipse.sphinx.emf.util.WorkspaceEditingDomainUtil;
import org.eclipse.sphinx.emf.workspace.ui.saving.BasicModelSaveablesProvider.SiteNotifyingSaveablesLifecycleListener;
import org.eclipse.sphinx.platform.util.PlatformLogUtil;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.ISaveablesLifecycleListener;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.SaveablesLifecycleEvent;
/**
* Extends the Eclipse compare editor in order to make model oriented.
*/
@SuppressWarnings("restriction")
public class ModelCompareEditor extends CompareEditor implements IModelEditorInputChangeAnalyzer {
/**
* The identifier of this editor (as contributed).
*/
public static String ID = "org.eclipse.sphinx.emf.compare.ui.editors.modelCompareEditor"; //$NON-NLS-1$
protected ModelEditorUndoContextManager undoContextManager;
protected ModelEditorInputSynchronizer editorInputSynchronizer;
/**
* Default constructor.
*/
public ModelCompareEditor() {
}
@Override
public void init(IEditorSite site, IEditorInput input) throws PartInitException {
super.init(site, input);
undoContextManager = getModelEditorUndoContextManager();
TransactionalEditingDomain editingDomain = getEditingDomains()[0] != null ? getEditingDomains()[0] : getEditingDomains()[1];
if (editingDomain != null) {
editorInputSynchronizer = new ModelEditorInputSynchronizer(input, editingDomain, this, new ModelCompareEditorInputChangeHandler());
}
}
protected ModelEditorUndoContextManager getModelEditorUndoContextManager() {
if (undoContextManager == null) {
undoContextManager = createModelEditorUndoContextManager();
}
return undoContextManager;
}
protected ModelEditorUndoContextManager createModelEditorUndoContextManager() {
TransactionalEditingDomain editingDomain = getEditingDomains()[0] != null ? getEditingDomains()[0] : getEditingDomains()[1];
return new ModelEditorUndoContextManager(getSite(), this, editingDomain);
}
@Override
public void dispose() {
if (undoContextManager != null) {
undoContextManager.dispose();
}
super.dispose();
}
/**
* @return
*/
public ISaveablesLifecycleListener createModelSaveablesLifecycleListener() {
return new SiteNotifyingSaveablesLifecycleListener(this) {
@Override
public void handleLifecycleEvent(SaveablesLifecycleEvent event) {
super.handleLifecycleEvent(event);
if (event.getEventType() == SaveablesLifecycleEvent.DIRTY_CHANGED) {
firePropertyChange(PROP_DIRTY);
}
}
};
}
@Override
public boolean isSaveOnCloseNeeded() {
// Model-based editors don't need to be saved when being closed even if the model is dirty, because they don't
// own the model. The model is loaded, managed, and saved globally, i.e. it is not destroyed but stays there
// when editors are being closed.
return false;
}
@Override
public boolean isSaveAsAllowed() {
// TODO Modify implementation as soon as saving as diff model would be available.
return false;
}
@Override
public Object getAdapter(@SuppressWarnings("rawtypes") Class key) {
if (key.equals(IUndoContext.class)) {
// Used by undo/redo actions to get their undo context
return getModelEditorUndoContextManager().getUndoContext();
}
return super.getAdapter(key);
}
/**
* @return An array of {@linkplain TransactionalEditingDomain editing domain}s which size is 2 and where at index 0
* is editing domain from left, at index 1 is editing domain from right.
*/
public TransactionalEditingDomain[] getEditingDomains() {
TransactionalEditingDomain[] editingDomains = new TransactionalEditingDomain[2];
Object[] modelRoots = getModelRoots();
if (modelRoots[0] != null) {
editingDomains[0] = WorkspaceEditingDomainUtil.getEditingDomain(modelRoots[0]);
}
if (modelRoots[1] != null) {
editingDomains[1] = WorkspaceEditingDomainUtil.getEditingDomain(modelRoots[1]);
}
return editingDomains;
}
/**
* @return The root objects of the model part that are currently being compared in this editor or an empty array if
* no such objects are available. Anyway, always returns an array of {@linkplain Object}s which size is 2
* and where at index 0 is the left root and at index 1 is the right root.
*/
public Object[] getModelRoots() {
Object[] modelRoots = new Object[2];
IEditorInput editorInput = getEditorInput();
if (editorInput instanceof ModelComparisonScopeEditorInput) {
modelRoots[0] = ((ModelComparisonScopeEditorInput) editorInput).getLeftObject();
modelRoots[1] = ((ModelComparisonScopeEditorInput) editorInput).getRightObject();
}
return modelRoots;
}
protected AdapterFactory[] getAdapterFactories() {
AdapterFactory[] adapterFactories = new AdapterFactory[2];
TransactionalEditingDomain[] editingDomains = getEditingDomains();
for (int i = 0; i < 2; i++) {
TransactionalEditingDomain editingDomain = editingDomains[i];
if (editingDomain != null) {
adapterFactories[i] = ((AdapterFactoryEditingDomain) editingDomain).getAdapterFactory();
}
}
return adapterFactories;
}
protected AdapterFactoryItemDelegator[] getItemDelegators() {
AdapterFactoryItemDelegator[] itemDelegators = new AdapterFactoryItemDelegator[2];
AdapterFactory[] adapterFactories = getAdapterFactories();
for (int i = 0; i < 2; i++) {
AdapterFactory adapterFactory = adapterFactories[i];
if (adapterFactory != null) {
itemDelegators[i] = new AdapterFactoryItemDelegator(adapterFactory);
}
}
return itemDelegators;
}
protected boolean isActivePart() {
return this == getSite().getWorkbenchWindow().getPartService().getActivePart();
}
@Override
public void setInput(IEditorInput input) {
if (input instanceof ModelComparisonScopeEditorInput) {
super.setInput(input);
} else {
PlatformLogUtil.logAsError(Activator.getPlugin(), new RuntimeException(Messages.error_invalidEditorInput));
}
}
@Override
public boolean containsEditorInputObject(IEditorInput editorInput, Set<EObject> objects) {
if (objects != null && editorInput instanceof ModelComparisonScopeEditorInput) {
Object leftObject = ((ModelComparisonScopeEditorInput) editorInput).getLeftObject();
Object rightObject = ((ModelComparisonScopeEditorInput) editorInput).getRightObject();
return objects.contains(leftObject) || objects.contains(rightObject);
}
return false;
}
@Override
public boolean containsEditorInputResourceURI(IEditorInput editorInput, Set<URI> resourceURIs) {
if (resourceURIs != null && editorInput instanceof ModelComparisonScopeEditorInput) {
Set<URI> editorInputResourceURIs = new HashSet<URI>();
Resource leftResource = ((ModelComparisonScopeEditorInput) editorInput).getLeftResource();
if (leftResource != null) {
editorInputResourceURIs.add(leftResource.getURI());
}
Resource rightResource = ((ModelComparisonScopeEditorInput) editorInput).getRightResource();
if (rightResource != null) {
editorInputResourceURIs.add(rightResource.getURI());
}
for (URI editorInputResourceURI : editorInputResourceURIs) {
if (resourceURIs.contains(editorInputResourceURI)) {
return true;
}
}
}
return false;
}
public class ModelCompareEditorInputChangeHandler extends DefaultModelEditorInputChangeHandler {
@Override
public void handleEditorInputObjectRemoved(IEditorInput editorInput, Set<EObject> removedObjects) {
close();
}
@Override
public void handleEditorInputObjectMoved(IEditorInput editorInput, Set<EObject> movedObjects) {
close();
}
@Override
public void handleEditorInputResourceMoved(IEditorInput editorInput, URI oldURI, URI newURI) {
// Do nothing because resource removed listener will be called
}
@Override
public void handleEditorInputResourceRemoved(IEditorInput editorInput) {
close();
}
/**
* Closes the editor programmatically.
*/
protected void close() {
Display display = getSite().getShell().getDisplay();
display.asyncExec(new Runnable() {
@Override
public void run() {
getSite().getPage().closeEditor(ModelCompareEditor.this, false);
}
});
}
/**
* Updates the editor.
*/
protected void updateEditorInput(IEditorInput oldEditorInput, IEditorInput newEditorInput) {
Assert.isNotNull(newEditorInput);
if (!newEditorInput.equals(oldEditorInput)) {
// Set new editor input
setInputWithNotify(newEditorInput);
// Update editor part title
setTitleToolTip(getTitleToolTip());
}
}
}
}