blob: 9c0388b8b99e25ee288a085c1faea69fd5aa7ad3 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2013, 2017 CEA LIST.
*
* All rights reserved. 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:
* CEA LIST - Initial API and implementation
*****************************************************************************/
package org.eclipse.papyrus.cdo.internal.ui.editors;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.dawn.gmf.editors.impl.DawnGMFEditorSupport;
import org.eclipse.emf.cdo.dawn.gmf.synchronize.DawnConflictHelper;
import org.eclipse.emf.cdo.dawn.gmf.util.DawnDiagramUpdater;
import org.eclipse.emf.cdo.dawn.spi.DawnState;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.ui.parts.GraphicalEditor;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramDropTargetListener;
import org.eclipse.gmf.runtime.diagram.ui.resources.editor.parts.DiagramDocumentEditor;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.util.TransferDropTargetListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.papyrus.cdo.core.resource.CDOAwareModelSet;
import org.eclipse.papyrus.cdo.internal.core.CDOUtils;
import org.eclipse.papyrus.cdo.internal.ui.Activator;
import org.eclipse.papyrus.cdo.internal.ui.decorators.CDOStateAdapter;
import org.eclipse.papyrus.cdo.internal.ui.dnd.CDOResourceURITransferData;
import org.eclipse.papyrus.cdo.internal.ui.dnd.ResourceDropActionDelegate;
import org.eclipse.papyrus.cdo.internal.ui.util.UIUtil;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
import org.eclipse.papyrus.infra.gmfdiag.common.DefaultGraphicalEditorSupport;
import org.eclipse.papyrus.infra.gmfdiag.common.editpart.IConflictingEditPartFilter;
import org.eclipse.papyrus.infra.gmfdiag.common.editpart.PapyrusDiagramEditPart;
import org.eclipse.ui.part.PluginTransfer;
import org.eclipse.ui.part.PluginTransferData;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
/**
* This is the DawnGraphicalEditorSupport type. Enjoy.
*/
public class DawnGraphicalEditorSupport extends DefaultGraphicalEditorSupport {
private final ServicesRegistry registry;
public DawnGraphicalEditorSupport(ServicesRegistry registry) {
super();
this.registry = registry;
}
@Override
public void initialize(GraphicalEditor editor) {
if (editor instanceof DiagramDocumentEditor) {
DiagramDocumentEditor diagramEditor = (DiagramDocumentEditor) editor;
CDOView view = getCDOView();
if (view != null) {
initialize(diagramEditor, view);
}
initializeCDOResourceDropSupport(diagramEditor);
}
super.initialize(editor);
}
protected void initialize(final DiagramDocumentEditor diagramEditor, CDOView view) {
DawnEditorAdapter adapter = new DawnEditorAdapter(diagramEditor);
final DawnGMFEditorSupport dawnSupport = new PapyrusGMFEditorSupport(adapter);
adapter.setEditorSupport(dawnSupport);
adapter.setView(getCDOView());
dawnSupport.setView(adapter.getView());
// after the root edit part has been created, inject a conflicting edit
// part filter
UIUtil.later(new Runnable() {
@Override
public void run() {
DiagramEditPart diagramEP = diagramEditor.getDiagramEditPart();
if (diagramEP instanceof PapyrusDiagramEditPart) {
((PapyrusDiagramEditPart) diagramEP).setConflictingEditPartFilter(createConflictingEditPartFilter());
}
}
});
dawnSupport.registerListeners();
// find and process objects locked remotely
final Map<Object, DawnState> remoteLocks = getRemoteLocks(diagramEditor);
if (!remoteLocks.isEmpty()) {
// post for later because the editor isn't yet connected to its
// editor site in the workbench
UIUtil.later(new Runnable() {
@Override
public void run() {
dawnSupport.handleRemoteLockChanges(remoteLocks);
for (Object next : remoteLocks.keySet()) {
final EObject element = CDOUtil.getEObject((CDOObject) next);
View view = DawnDiagramUpdater.findViewByContainer(element);
CDOStateAdapter.setState(view, remoteLocks.get(next));
}
}
});
}
}
CDOView getCDOView() {
CDOView result = null;
try {
ModelSet modelSet = registry.getService(ModelSet.class);
if (modelSet instanceof CDOAwareModelSet) {
result = ((CDOAwareModelSet) modelSet).getCDOView();
}
} catch (ServiceException e) {
Activator.log.error(e);
}
return result;
}
private Map<Object, DawnState> getRemoteLocks(DiagramDocumentEditor diagramEditor) {
Map<Object, DawnState> result = Maps.newHashMap();
Diagram diagram = diagramEditor.getDiagram();
if (diagram != null) {
Iterator<EObject> iter = EcoreUtil.getAllProperContents(Collections.singleton(diagram), false);
while (iter.hasNext()) {
CDOObject next = CDOUtils.getCDOObject(iter.next());
if ((next != null) && CDOUtils.isLocked(next, true)) {
result.put(next, DawnState.LOCKED_REMOTELY);
}
}
}
return result;
}
private IConflictingEditPartFilter createConflictingEditPartFilter() {
return new IConflictingEditPartFilter() {
@Override
public boolean isConflicting(EditPart editPart) {
Object model = editPart.getModel();
return (model instanceof EObject) && DawnConflictHelper.isConflicted((EObject) model);
}
};
}
protected void initializeCDOResourceDropSupport(final DiagramDocumentEditor diagramEditor) {
// after the root edit part has been created, inject drop-target listener for dropping hyperlinks to CDO resources by URI
UIUtil.later(new Runnable() {
@Override
public void run() {
EditPartViewer viewer = diagramEditor.getDiagramGraphicalViewer();
viewer.addDropTargetListener(createCDOResourceURIDropTargetListener(viewer));
}
});
}
private TransferDropTargetListener createCDOResourceURIDropTargetListener(EditPartViewer viewer) {
return new DiagramDropTargetListener(viewer, PluginTransfer.getInstance()) {
@Override
protected boolean isDataTransfered() {
// I only have my data when the actual transfer data carrying my URIs is available
return getCurrentEvent().data != null;
}
@Override
protected List<EObject> getObjectsBeingDropped() {
List<EObject> result = null;
CDOResourceURITransferData uriData = null;
if (PluginTransfer.getInstance().isSupportedType(getCurrentEvent().currentDataType) && !localTransferHasObjectFromThisRepo()) {
Object data = getCurrentEvent().data;
if (data instanceof PluginTransferData) {
PluginTransferData ptData = (PluginTransferData) data;
if (ResourceDropActionDelegate.DROP_ACTION_ID.equals(ptData.getExtensionId())) {
uriData = CDOResourceURITransferData.deserialize(ptData.getData());
}
}
}
if (uriData == null) {
result = Collections.emptyList();
} else {
// convert the URI transfer data to an EObject so that the drag-and-drop
// system doesn't bomb on ClassCastExceptions
result = Collections.singletonList(uriData.asEObject());
}
return result;
}
};
}
boolean localTransferHasObjectFromThisRepo() {
boolean result = false;
CDOView view = getCDOView();
if (view != null) {
IStructuredSelection sel = CDOUtils.tryCast(LocalSelectionTransfer.getTransfer().getSelection(), IStructuredSelection.class);
if ((sel != null) && !sel.isEmpty()) {
for (EObject next : Iterables.filter(sel.toList(), EObject.class)) {
CDOObject cdo = CDOUtils.getCDOObject(next);
if ((cdo != null) && (cdo.cdoView().getSession() == view.getSession())) {
result = true;
break;
}
}
}
}
return result;
}
}