Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » Papyrus » API for creating and accessing uml diagrams(I am looking for a starting point how to programatically create diagrams in my existing model)
API for creating and accessing uml diagrams [message #1708013] Fri, 11 September 2015 12:59 Go to next message
Hans Huckebein is currently offline Hans HuckebeinFriend
Messages: 15
Registered: January 2015
Junior Member
can anybody point me such a starting point? I do not need much more than

- create new diagram
- insert existing model entities
- automatically layout

=> these steps are possible clicking through the gui, but i could not find out how to do it programmatically from my plugin. There must be an object factory for diagrams or something like that. I would be grateful for any help.

best regards
Hans
Re: API for creating and accessing uml diagrams [message #1708054 is a reply to message #1708013] Fri, 11 September 2015 21:01 Go to previous messageGo to next message
Johan Van Noten is currently offline Johan Van NotenFriend
Messages: 87
Registered: July 2009
Member
Hi Hans,

I'm not an expert on this topic either, so follow my suggestion below with some precaution...

I had the need to create an ActivityDiagram programmatically and used the following code for it. Didn't try any other diagram types, but I guess there is some analogy...

	public static Diagram createActivityDiagram(Activity owner, String name) {
		ModelSet modelSet = null;
		ResourceSet resourceSet = owner.eResource().getResourceSet();
		if (resourceSet instanceof ModelSet) {
			modelSet = (ModelSet) resourceSet;
		} else {
			return null;
		}

		final Resource notationResource = NotationUtils.getNotationResource(modelSet);
		Diagram diagram = NotationUtils.getAssociatedDiagram(notationResource, owner);
		if (diagram == null) {
			// Create one
			CreateActivityDiagramCommand createDiagramCommand = new CreateActivityDiagramCommand();
			diagram = createDiagramCommand.createDiagram(modelSet, owner, name);
		}

		// Check the diagram
		if (!name.equals(diagram.getName())) {
			diagram.setName(name);
		}
		return diagram;
	}
Re: API for creating and accessing uml diagrams [message #1708180 is a reply to message #1708013] Mon, 14 September 2015 12:10 Go to previous messageGo to next message
Camille Letavernier is currently offline Camille LetavernierFriend
Messages: 952
Registered: February 2011
Senior Member
Hi,

For displaying existing elements in a Diagram, you have two options:

- GMF ViewService: you need to know the semantic element to display, and the target GMF View (e.g. specific compartment when dropping a Property in a Class). You also need the graphical hint to create (Which might be complex to obtain in a generic way)

Example:

EObject objectToDisplay = ...;
View targetView = ...; //May be the diagram or a diagram element (Compartment...)
ViewService viewService = ViewService.getInstance();
String hint = "..."; //e.g. "2008" for a Class in a Class Diagram
PreferencesHint diagramPrefHint = UMLDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT; //There is one for each kind of diagram
Node newNode = ViewService.createNode(targetView, objectToDisplay, hint, diagramPrefHint);


This approach doesn't require the diagram to be opened (You work directly at the notation model level), but it may be complex to get all the required info (e.g. exact target View and semantic Hint)

- DropObjectsRequest: this one is much simpler to use, as it will behave exactly like it would if you manually dropped an element from the ModelExplorer to the Diagram. You only need to specify the Semantic EObject, the target element (EditPart) and the mouse coordinates (Optional, especially if you rely on the automatic layout later on)

Example:

EditPart targetEditPart = ...;
Element objectToDisplay = ...;
DropObjectsRequest dropObjectsRequest = new DropObjectsRequest();
List<Element> list = Collections.singletonList(elementToShow)
dropObjectsRequest.setObjects(list);
dropObjectsRequest.setLocation(new Point(20, 100 * position));
Command commandDrop = targetEditPart.getCommand(dropObjectsRequest);


This second approach does a little bit more than displaying, as it will go through the entire Drag & Drop mechanism, which is customizable in Papyrus. So in some cases, you may get a graphical popup asking for a choice (When several drop strategies are available). You can disable this popup (and always use the default strategy) by adding a parameter to the drop request:

org.eclipse.papyrus.infra.gmfdiag.common.utils.RequestUtils.setUseGUI(dropObjectsRequest, false)


(Note that all the code given as examples are untested fragments. In any case, you need to wrap execution in a Transaction, using the EditingDomain, CommandStack and Commands)

Regarding the Automatic Layout, we don't provide anything specific in Papyrus. All layout actions are natively provided by either GEF or GMF, or extensions such as Zest or Eclipse Layout Kernel (ELK)

HTH,
Camille


Camille Letavernier
Re: API for creating and accessing uml diagrams [message #1708536 is a reply to message #1708180] Thu, 17 September 2015 10:45 Go to previous messageGo to next message
Hans Huckebein is currently offline Hans HuckebeinFriend
Messages: 15
Registered: January 2015
Junior Member
Thank you for your answers! That helped me much, I got started but still have problems; probably I am not walking on the intended paths. Here I describe my first results, maybe other users can benefit.

Johans post led me to the CreateClassDiagramCommand class that is the starting point for creating a class diagram.

Comment copied from the superclass:
/**
 * Command creating a new GMF diagram in Papyrus. This command is intended to be used in eclipse
 * extensions.
* [...]
*/


But: just calling "cmd.createDiagram()" failed. In the debugger I saw that the policyChecker's "applicableViewpoints" contains a Viewport that has icon and name already set:

// just for inspecting:
// ViewPrototype proto = ViewPrototype.get(cmd.getCreatedDiagramType(), myComponent, myComponent);


and this does not match the matching criteria implemented in policyCheckers "matches()" method (bug or wrong usage?).
I finally was able to create a class diagram by taking the prototype from policyCheckers list "getPrototypesFor(myComponent)"; I took that one with "PapyrusUMLClassDiagram" (cmd.getCreatedDiagramType() ) as implementationID, and called

 Diagram myDiagram=cmd.createDiagram(modelSet, myComponent, myComponent, proto, name);


that works and creates an inner class diagram within myComponent. For creating and inserting nodes I need, as Camille described above, its (appropriate!?) visual_id, that is what I not yet understand. The code below works for inserting classes in my inner class diagram:

TreeIterator<EObject> objIterator = myComponent.eAllContents();
while (objIterator.hasNext()) {
	EObject eachObject = objIterator.next();
	int	typeHint=XIDLDiagramUtil.getNodeVisualID(myDiagram,eachObject);
	PreferencesHint diagramPrefHint = UMLDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT; //There is one for each kind of diagram
	TransactionalEditingDomain ted=TransactionUtil.getEditingDomain(myDiagram);

	if (typeHint >0 && ted != null){
		ted.getCommandStack().execute(new RecordingCommand(ted){
			@Override protected void doExecute(){ 
				Node newNode = ViewService.createNode(myDiagram, eachObject,Integer.toString(typeHint), diagramPrefHint);
				System.out.println(newNode.getType()+" created and inserted into "+myDiagram.getName());
		       } 
	       } ); // end inline override
	}
	else
		System.out.println(eachObject+" is not represented.");
}
return myDiagram;


But not for Generalizations. As visual_ID for that I take GeneralizationEditPart.VISUAL_ID, do I need a different target view?

Here is my delegate for retreiving the visual id.

private static int getNodeVisualID(Diagram myDiagram, EObject eObject) {
		
	int hint=org.eclipse.papyrus.uml.diagram.clazz.part.UMLVisualIDRegistry.getNodeVisualID(myDiagram,eObject);
	if(hint>0)
		return hint;
	if (UMLPackage.eINSTANCE.getGeneralization().isSuperTypeOf(eObject.eClass())) {
				return GeneralizationEditPart.VISUAL_ID;
			}
	return -1;
	}


That is quite complicated and I needed to search a lot around in the code - is there no api-documentation that I can rely on? How could I know about the command classes and the visual_id registry ... Crying or Very Sad more hints would be helpfull.

best
Hans

PS
there seems to be a little bug that in line 336 of AbstractPapyrusGmfCreateDiagramCommandHandler; it does abort on viewPrototype==null but the callee newer answers null but a special "UNAVAILABLE_VIEW" instead.

[Updated on: Thu, 17 September 2015 11:00]

Report message to a moderator

Re: API for creating and accessing uml diagrams [message #1708542 is a reply to message #1708536] Thu, 17 September 2015 11:37 Go to previous messageGo to next message
Hans Huckebein is currently offline Hans HuckebeinFriend
Messages: 15
Registered: January 2015
Junior Member
oh I thought that node was synonym for visual object; I had overseen that I can also create edges .... will try it. But all that code I am currently writing must be already there somewhere? I am not the first who wants to insert different visual objects into a diagram....
Re: API for creating and accessing uml diagrams [message #1708546 is a reply to message #1708542] Thu, 17 September 2015 11:47 Go to previous messageGo to next message
Camille Letavernier is currently offline Camille LetavernierFriend
Messages: 952
Registered: February 2011
Senior Member
Hi Hans,

In Papyrus, most of this code is either generated (Via GMF Tooling code generators), or implemented by GMF generic actions (Drag & Drop, Palette creation...)

We don't provide any specific API for clients to display arbitrary elements, so they have to rely on these low-level APIs as well (Or slightly higher level Drop Requests)

Regards,
Camille


Camille Letavernier
Re: API for creating and accessing uml diagrams [message #1708562 is a reply to message #1708546] Thu, 17 September 2015 13:09 Go to previous message
Hans Huckebein is currently offline Hans HuckebeinFriend
Messages: 15
Registered: January 2015
Junior Member
in between I managed to implement the drop-variant of my task and the auto-arrange. Here is the code (also based on post http://stackoverflow.com/questions/11968509 ) that is probably not absolutely clean (maybe it works only because I opened the concerned editPart just before):

Shell myShell=PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
EditPart editPart = OffscreenEditPartFactory.getInstance().createDiagramEditPart(myDiagram, myShell);

DropObjectsRequest dropObjectsRequest = new DropObjectsRequest();
dropObjectsRequest.setObjects(list);
//dropObjectsRequest.setLocation(new Point(20, 100 ));
org.eclipse.gef.commands.Command commandDrop = editPart.getCommand(dropObjectsRequest);
if(commandDrop!=null && commandDrop.canExecute())
	commandDrop.execute();
		
List<EditPart> editParts = CollectionUtil.createNewSequence();
editParts.add(editPart);
ArrangeRequest request = new ArrangeRequest(ActionIds.ACTION_ARRANGE_ALL, LayoutType.RADIAL);
request.setPartsToArrange(editParts);
org.eclipse.gef.commands.Command cmdArrange = editPart.getCommand(request);
if (cmdArrange != null)
	cmdArrange.execute();
Previous Topic:UML Attributes vs. SYSML Properties
Next Topic:Help I don't have Layers on Papyrus 1.1
Goto Forum:
  


Current Time: Fri Mar 29 12:06:12 GMT 2024

Powered by FUDForum. Page generated in 0.04258 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top