Bug 514645 - Drag and drop support from non Sirius editors or views
Summary: Drag and drop support from non Sirius editors or views
Status: NEW
Alias: None
Product: Sirius
Classification: Modeling
Component: Diagram (show other bugs)
Version: 3.1.0   Edit
Hardware: All All
: P3 enhancement with 1 vote (vote)
Target Milestone: ---   Edit
Assignee: Emmanuel Chebbi CLA
QA Contact:
URL:
Whiteboard:
Keywords: triaged
Depends on:
Blocks:
 
Reported: 2017-04-03 10:26 EDT by Jonathan Pepin CLA
Modified: 2019-06-28 03:10 EDT (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Pepin CLA 2017-04-03 10:26:24 EDT
After investigating on the drag and drop mechanism, I understand that Sirius does not allow to drop object from resource not known by the current session because eObjects referred by a diagram have to be managed by a single resourceSet.

It exists a trick to work around this technical constraint : using the eObject URI to find the corresponding eObject in the Sirius’ resourceSet :

        private EObject getEObjectFromSessionResourceSet(final EObject incommingEObject) {
            final URI uri = EcoreUtil.getURI(incommingEObject);
            return getSession().getSessionResource().getResourceSet().getEObject(uri, true);
        }

You can find in attachment a patch proposing this improvement. The impacted method is org.eclipse.sirius.diagram.ui.tools.internal.editor.DDiagramEditorImpl.DDiagramEditorTransferDropTargetListener.createTargetRequest().
Comment 1 Eclipse Genie CLA 2017-04-03 10:39:30 EDT
New Gerrit change created: https://git.eclipse.org/r/94305
Comment 2 Pierre-Charles David CLA 2017-04-04 05:12:07 EDT
Hi,

Thanks for this patch. we'll try to have a closer look this week, but at first glance the getEObjectFromSessionResourceSet() method may be too simple. Session.addSemanticResource() should probably be used instead of an implicit load of the new resource, to make sure the new model is properly registered and integrated in the session.

I'm also wondering if such an operation (adding a new semantic resource to the session) should ask for confirmation (maybe optionally). There's an argument for making it as transparent as possible (as in your patch) to reduce frictions, but adding a new resource can have side-effects (in terms of performances, of dependencies...). Maybe a confirmation popup "This will add model M as a new dependency on project/session P. Proceed/Cancel".
Comment 3 Jonathan Pepin CLA 2017-04-04 05:44:39 EDT
Thanks you for your feedback. Obviously, in our proposed patch, the object could be added only if the resource is present in the semantic resource collection of the session. So, the problem manage the drop between two different resource sets. The proposed patch expects to have already loading the semantic resource on the session to do that, we use a sessionlisternermanager to register the resource on semantic resources.
Thus, the resource is known by the session. During the drop, the deal is to found the equivalent in the loaded semantic resource, instead of the resource from the drag source (which is not handled by the sirius session resource set).

To more understand our investigation, you can find bellow the session listener manager.

                public void notifyAddSession(final Session newSession) {
                               final URI ourResourceUri = "uri://ourResource";
                               final TransactionalEditingDomain transacEditDomain = newSession
                                                               .getTransactionalEditingDomain();
                               if (transacEditDomain == null) {
                                               throw new IllegalStateException(
                                                                              "Resource can't be loaded without TransactionalEditingDomain");
                               }
                               final TransactionalCommandStack transacCmdStack = (TransactionalCommandStack) transacEditDomain
                                                               .getCommandStack();
                               final Command cmd = new RecordingCommand(transacEditDomain) {
                                               @Override
                                               protected void doExecute() {
                                                               newSession.addSemanticResource(discoResourceUri,
                                                                                              new NullProgressMonitor());
                                               }
                               };
                               transacCmdStack.execute(cmd);
                }
Comment 4 Pierre-Charles David CLA 2017-04-07 10:33:48 EDT
One thing that worries me is that a plain URI may not translate to the "same" element in two different ResourceSets. For example URIs which use XPath-like references to "the 3rd child of element X"; in the session's ResourceSet this may not translate to the same logical element the user dropped from the origin ResourceSet, with confusing results. Even if it resolves to the same *logical* element, that element may not be in the same state in both ResourceSets (maybe some attributes have been edited, but not saved, in the origin context, and the version in the session's ResourceSet will not match what the user thought he was tranfering). This is not even considering ResourceSet-specific URIHandlers & URIConverters, which may produce different results.

These may not be an issue in your own case, but if such a mechanism were included in Sirius itself they will need to be considered.

Another approach would be to let specifiers decide if and how they want to handle these "external drops" in their modelers, by giving them all the information they need in their "Container Drop" tools. We already do something similar to this for files & folders dropped in diagrams: WorkspaceDragAndDropSupport.convert(Object, Session) wraps IFiles & IFolders into DFile/DFolder elements (which are EClasses defined by Sirius), that can then be fed to the tools (which expect EObjects).

We could introduce a similar kind of wrapper, say, DExternalEObject, which exposes the URI of the original EObject as an attribute. It would then be the responsibility of the specifiers to decide what to do with that. In your case you would invoke a Java service which does essentially what your getEObjectFromSessionResourceSet() method does.
Comment 5 Jonathan Pepin CLA 2017-05-16 05:30:20 EDT
The specific wrapper DExternalEObject with URI attribute seems to be a promising solution.
Do you have planned to proposed a patch for this feature ?
Comment 6 Pierre-Charles David CLA 2017-05-17 03:35:15 EDT
(In reply to Jonathan Pepin from comment #5)
> The specific wrapper DExternalEObject with URI attribute seems to be a
> promising solution.
> Do you have planned to proposed a patch for this feature ?

It's not on the roadmap right now. We're finishing Sirius 5.0 for the Oxygen release, so we don't have time to look into this for the moment. It will be considered for 5.1 (planned for next October), but I can't make any guarantee (unless you're willing to sponsor the development).
Comment 7 Pierre-Charles David CLA 2019-01-02 05:42:23 EST
See also the related scenario mentioned in https://www.eclipse.org/forums/index.php?t=msg&th=1096824&goto=1800418&#msg_1800418
Comment 8 Emmanuel Chebbi CLA 2019-05-05 17:40:05 EDT
I am the one who created the thread mentioned by Pierre-Charles. I write this comment to add a few details about my use case.

Short version: I have a view that displays a library of components, and I'd like to allow the user to add some of them to his diagram by drag'n'drop.

Long version: I would like to create a Sirius editor allowing to design a data-flow. The data can undergo transformations. Each transformation is represented in the editor as a box. The user must be able to add as many transformations as he wants.

There are numerous kinds of transformations, and many of them are provided by extension points.

The key point is that I want these transformations to be shown in a separate view in order to provide:
 - a custom display (tree view, icons, popup, contextual menu, etc.)
 - filters.

This view would thus constitute a "library of transformations". In order to add one transformation to the data flow, the user would just have to drag a transformation from the view and to drop it in the Sirius editor.

This approach is already used by many (non Sirius-based) editors and I believe that Sirius could greatly benefit from this feature. Examples of such editors are:
 - Stimulus [1], to express complex requirements from a library of constraints
 - EASE [2], to automatically import Python modules in the shell
 - most of website WYSIWYG editors [3], to build website's UI

 [1] https://www.argosim.com/home/product-overview/
 [2] https://www.eclipse.org/ease/
 [3] https://visualcomposer.com/features/drag-and-drop-website-builder/
Comment 9 Emmanuel Chebbi CLA 2019-06-27 19:29:10 EDT
As discussed in the mailing list [1] I would be glad to work on this.

What I suggest is that I start with taking a look at the code, get familiar with it and check how DFile and DFolder are managed, and then attempt to propose a patch.

If I struggle to understand some parts of the code, should I ask my questions by posting a new comment on this thread or rather use the forum or the mailing list?

 [1] https://www.eclipse.org/lists/sirius-dev/msg00256.html
Comment 10 Pierre-Charles David CLA 2019-06-28 03:10:38 EDT
Great, thanks! I'm assigning the ticket to you.

If your questions concern the overal contribution process, coding guidelines, etc., I think using the mailing list would be better as it will be more visible and could eventually be useful to others.

If they are more specific to this particular issue, the bugzilla is the best place.

To understand how the current mechanism works, a good starting point is to look at where org.eclipse.sirius.viewpoint.description.tool.DragSource and org.eclipse.sirius.viewpoint.DFolder/DFile/DResource are referenced. Basically you will have to add support for the new type of DragSource (say, DragSource.EXTERNAL_EOBJECT) with the corresponding data types to represent them at runtime (similar to what DFile/DFolder do, say DExternalEObject).

If the specifier of a Drop Tool (org.eclipse.sirius.diagram.description.tool.ContainerDropDescription) indicates that it supports this new kind of source (it should not by default, to avoid breaking existing tools), then at runtime when the user tries a DnD operation accept it (org.eclipse.sirius.diagram.ui.graphical.edit.internal.policies.validators.DragAndDropValidator.isValidDragAndDropRequestForElementFromEclipseView()) by wrapping the dragged element into a DExternalEObject (like we wrap IFiles into DFiles, see org.eclipse.sirius.business.api.resource.WorkspaceDragAndDropSupport.convert(Object, Session)). Then, when building the actual command that will be executed (org.eclipse.sirius.diagram.tools.internal.command.builders.DragAndDropCommandBuilder.buildDropInContainerCommandFromTool(EObject, EObject, EObject, EObject)) make sure the tool's implementation (the operations below the "Begin" element in the .odesign file) have enough information to detect "this is a drop of an external EObject, and this is the EObject in question" and then it's up to it to decide what to do (your implementation should not presume what the tool will want to do, just ensure it has the information it needs).

Of course this is from a quick glance at the code and what I remember from the last time I had to work with it, so take this with a grain of salt as a starting point.