Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » Papyrus » How to obtain graphical Object from EditPart
How to obtain graphical Object from EditPart [message #1076250] Wed, 31 July 2013 03:00 Go to next message
jonas b is currently offline jonas b
Messages: 23
Registered: July 2013
Junior Member
Hi,
In Papyrus for Kepler release I want to make visual changes to a .di-diagram by code. I managed to obtain an EditPart from the active Editor which holds a diagram from a .di-file. From here what's the next step to modify the appearance of the diagram's elements? Do I have to obtain a org.eclipse.gmf.runtime.notation.impl.ShapeImpl or a org.eclipse.draw2d.Figure? And how would I get these objects?
Re: How to obtain graphical Object from EditPart [message #1076550 is a reply to message #1076250] Wed, 31 July 2013 15:11 Go to previous messageGo to next message
Camille Letavernier is currently offline Camille Letavernier
Messages: 457
Registered: February 2011
Senior Member
Hi,


You can obtain the notation::View (gmf.runtime.notation.View) with the following code:

View view = (View)editPart.getAdapter(View.class);


Then you can obtain the style with:

ShapeStyle style = (ShapeStyle)view.getStyle(NotationPackage.eINSTANCE.getShapeStyle());


(You can retrieve any kind of GMF Style with this method)

Then, to edit the style:

style.setBold(true);


Note: before editing the style, you may need to start a transaction


Regards,
Camille


Camille Letavernier
Papyrus developer
Re: How to obtain graphical Object from EditPart [message #1078654 is a reply to message #1076550] Sat, 03 August 2013 10:11 Go to previous messageGo to next message
jonas b is currently offline jonas b
Messages: 23
Registered: July 2013
Junior Member
Hello Camille,
Thanks for your reply. I think I should elaborate a bit what I am actually trying to do.

I am writing a plugin which consists of a view. In this view I want to display state machine diagrams. The view is read-only, ie the user must not be able to edit the diagram through the view. The plugin however must be able to edit the appearance of any figure in the diagram. (The purpose of the plugin is to show the active state of the state machine. It does that by increasing line width of the current state for example.)

Since the view is read-only, I do not need anything from the EditPart tree or from the Model tree. I only need the IFigure tree. In other words: I only need the right part of this structure:
http://help.eclipse.org/kepler/topic/org.eclipse.gef.doc.isv/guide/images/factory.gif

The view must be able to display multiple instances of the same diagram. Therefore I need a deep copy of the entire IFigure tree starting from the root figure obtained by rootEditPart.getFigure() going down to every single leaf. Otherwise it would not be possible to add multiple instances of the same diagram to a common root figure or alter their appearance independently of each other. To achieve this deep copy, I see 2 possibilities:

1) I could write a cloning class which provides a method to recursively clone every single IFigure in the hierarchy. This approach is very tedious, since an empty state machine created by Papyrus already consists of 20+ IFigures. I would have to provide a copy method specific to every single subtype of IFigure. I took a look at the type hierarchy, it's huge.

2) Since I have the diagrams available as a combination of .di, .notation and .model files, it would be much easier to simply read these files and create any amount of instances anew. However I haven't found the place yet where this is done. Does the Papyrus project read in these files and construct its various diagrams? I suppose so, since many Elements are classes defined in Papyrus. Can you please point me to the plugin responsible for this task, so I can reuse the code for my plugin?


Re: How to obtain graphical Object from EditPart [message #1079908 is a reply to message #1076250] Mon, 05 August 2013 08:19 Go to previous messageGo to next message
Camille Letavernier is currently offline Camille Letavernier
Messages: 457
Registered: February 2011
Senior Member
Hi Jonas,


OK, I see what you're trying to do.

Quote:
Since the view is read-only, I do not need anything from the EditPart tree or from the Model tree. I only need the IFigure tree. In other words: I only need the right part of this structure:


Yes; this includes EditParts (Not only Figures). Actually, you should never access Figures directly.

Quote:
The view must be able to display multiple instances of the same diagram. Therefore I need a deep copy of the entire IFigure tree starting from the root figure obtained by rootEditPart.getFigure() going down to every single leaf. Otherwise it would not be possible to add multiple instances of the same diagram to a common root figure or alter their appearance independently of each other. To achieve this deep copy, I see 2 possibilities:


You can open the same diagram twice, programmatically, using the Papyrus IPageManager service. This will open a new tab (nested editor) on the same diagram, and duplicate the EditPart tree. They will still share the same Notation Model.

Diagram diagram = ...;
IPageManager pageManager = ServiceUtilsForEObject.getInstance().getIPageManager(diagram);
pageManager.openPage(diagram);


But then there's an issue: most EditParts have style setters, but they are protected. And Figures should not be manipulated either.

Moreover, even if you manage to change the style of an EditPart or a Figure, it will be overridden as soon as the diagram is refreshed (Because it will recompute its style from its notation Model)


There's another way to achieve this, with Diagram Stylesheets. CSS Stylesheets are used in Papyrus to dynamically compute the appearance of a Notation Model element. They also support a little bit of animation. However, as they are used on the Notation Model, you can't have multiple instances of the same diagram with different appearances (Because they share the same Notation Model). Currently, the best way to do that would be to duplicate the Diagram in the Notation Model.


So, currently, it is complicated to apply two different appearances to the same notation::Diagram. Everything else can be achieved rather easily through Stylesheets.


Regards,
Camille


Camille Letavernier
Papyrus developer
Re: How to obtain graphical Object from EditPart [message #1079948 is a reply to message #1076250] Mon, 05 August 2013 09:16 Go to previous messageGo to next message
jonas b is currently offline jonas b
Messages: 23
Registered: July 2013
Junior Member
Quote:
Moreover, even if you manage to change the style of an EditPart or a Figure, it will be overridden as soon as the diagram is refreshed (Because it will recompute its style from its notation Model)

Would it be possible to somehow deregister a Figure from the refreshing mechanism?

Quote:
However, as they are used on the Notation Model, you can't have multiple instances of the same diagram with different appearances (Because they share the same Notation Model). Currently, the best way to do that would be to duplicate the Diagram in the Notation Model.

Could you please explain "duplicating the diagram in the notation model"? Because it seems that cloning the diagram is the only way to go. I am currently inspecting the org.eclipse.papyurs.xwt package which has some methods like XWT.load() for example. Can I load a diagram from file with that?
Re: How to obtain graphical Object from EditPart [message #1080011 is a reply to message #1076250] Mon, 05 August 2013 11:11 Go to previous messageGo to next message
Camille Letavernier is currently offline Camille Letavernier
Messages: 457
Registered: February 2011
Senior Member
Hi,

Quote:
Would it be possible to somehow deregister a Figure from the refreshing mechanism?


No

Quote:
Could you please explain "duplicating the diagram in the notation model"? Because it seems that cloning the diagram is the only way to go. I am currently inspecting the org.eclipse.papyurs.xwt package which has some methods like XWT.load() for example. Can I load a diagram from file with that?


All models in Papyrus are EMF Models. You will have more luck with the org.eclipse.emf.* packages.


Have a look at the following test plug-ins in Papyrus, to see how we manipulate our models:

org.eclipse.papyrus.infra.gmfdiag.css.tests (See CSSStylesheetTest: pure-EMF model loading)


org.eclipse.papyrus.editor.integration.tests (See PageManagerTests: Multiple ways of opening and manipulating diagrams in a Papyrus editor)


To clone a diagram, see EcoreUtil.copy(T), from EMF: org.eclipse.emf.ecore.util.EcoreUtil


Regards,
Camille


Camille Letavernier
Papyrus developer
Re: How to obtain graphical Object from EditPart [message #1080656 is a reply to message #1080011] Tue, 06 August 2013 08:10 Go to previous messageGo to next message
jonas b is currently offline jonas b
Messages: 23
Registered: July 2013
Junior Member
Thank you for the examples! I managed to load a diagram from file and clone it using the examples you gave. As a result I now have 2 different instances of CSSDiagram obtained from the same notation file. That's exactly what I want.

Only 1 last piece is missing: I haven't found a way yet to directly draw an EObject on the screen. Looking at swt.widget classes like Control or Canvas, there's no way to pass an EObject directly. I guess it needs to be wrapped somehow..? but how?
Re: How to obtain graphical Object from EditPart [message #1080698 is a reply to message #1080656] Tue, 06 August 2013 09:21 Go to previous messageGo to next message
Camille Letavernier is currently offline Camille Letavernier
Messages: 457
Registered: February 2011
Senior Member
Hi,


What do you mean "Draw an EObject on the screen"?

The GMF (simplified) algorithm is the following, when the editor is opened:

Create Draw2D Canvas
read notation model
	for each notation View
		EditPart = EditPartFactory.getEditPart(View)
		EditPart.drawFigure(Canvas)


The notation View is associated to a UML Element: the EditPart reads the semantic information from the UML Element, and the graphical/style appearance from the notation View. The EditPart is responsible for drawing the right Figure (Because each UML Element has a specific graphical representation, and most elements can have different representations)

So, you have the following Model/View/Controller concepts:

- The UML Model (Semantic Model / EMF)
- The Notation Model (Graphical Model / EMF)
- The EditParts (Controller / GEF-GMF)
- The Figure (View / Draw2D)


Camille


Camille Letavernier
Papyrus developer
Re: How to obtain graphical Object from EditPart [message #1085876 is a reply to message #1080698] Tue, 13 August 2013 13:38 Go to previous messageGo to next message
jonas b is currently offline jonas b
Messages: 23
Registered: July 2013
Junior Member
I see. I followed the strategies in your test cases. To load a diagram from a file, I did the following:
private CSSDiagram init(URI uri) {
	ResourceSet resourceSet = new ResourceSetImpl();
	CSSHelper.installCSSSupport(resourceSet);
	try {
		return (CSSDiagram) EMFHelper.loadEMFModel(resourceSet, uri);
	} catch (IOException ex) {}
	return null;
}

@Override
public void createPartControl(Composite parent) {
	URI uri = URI.createPlatformPluginURI(AnimateActivator.PLUGIN_ID + "/Ampel/model.notation", true);
	Diagram diagram = init(uri);
}

Now that I have my Diagram, how can I build the whole structure including EditParts, and views without opening an editor? Because I'm extending ViewPart and eventually I want to draw onto a View, not an Editor.

I did the following:
@Override
public void createPartControl(Composite parent) {
	URI uri = URI.createPlatformPluginURI(AnimateActivator.PLUGIN_ID + "/Ampel/model.notation", true);
	Diagram diagram = init(uri);
	
	EditPartViewer viewer = new DiagramGraphicalViewer();
	viewer.setEditPartFactory(new UMLEditPartFactory());
	viewer.setRootEditPart(new ScalableRootEditPart());
	viewer.createControl(parent);
	viewer.setContents(diagram);
}

but I got NPE because of missing EditingDomain. So I created the resource set from an editing domain:
private CSSDiagram init(URI uri) {
	TransactionalEditingDomain domain = TransactionalEditingDomain.Factory.INSTANCE.createEditingDomain();
	domain.createResource(uri.toPlatformString(true));
	ResourceSet resourceSet = domain.getResourceSet();
	
	CSSHelper.installCSSSupport(resourceSet);
	try {
		return (CSSDiagram) EMFHelper.loadEMFModel(resourceSet, uri);
	} catch (IOException ex) {}
	return null;
}

Now I get a big pink rectangle inside the view, followed by an NPE and many, many messages like this:
!ENTRY org.eclipse.gmf.runtime.draw2d.ui 2 2 2013-08-13 16:13:55.351
!MESSAGE MapModeUtil#getMapMode(IFigure fig) fig parameter must be attached to a parent - using default MapMode

The NPE is caused by org.eclipse.gmf.runtime.diagram.ui.editpolicies.DiagramPopupBarEditPolicy.addPaletteListener and I presume it's because there is no host editpart present.

[Updated on: Tue, 13 August 2013 14:18]

Report message to a moderator

Re: How to obtain graphical Object from EditPart [message #1087943 is a reply to message #1076250] Fri, 16 August 2013 10:23 Go to previous message
jonas b is currently offline jonas b
Messages: 23
Registered: July 2013
Junior Member
I have a solution (found it here: http://www.eclipse.org/forums/index.php?t=msg&th=58758/)
private CSSDiagram createDiagram() {
	URI notationUri = URI.createPlatformPluginURI(AnimateActivator.PLUGIN_ID + "/Ampel/model.notation", true);
	ResourceSet resourceSet = new ResourceSetImpl();
	CSSHelper.installCSSSupport(resourceSet);
	TransactionalEditingDomain domain = DiagramEditingDomainFactory.getInstance().createEditingDomain(resourceSet);
	CSSDiagram diagram = null;
	try {
		diagram = (CSSDiagram)EMFHelper.loadEMFModel(resourceSet, notationUri);
	} catch (IOException e) {
		e.printStackTrace();
	}
	return diagram;
}

private DiagramGraphicalViewer createViewer(Diagram diagram, Composite parent) {
	DiagramGraphicalViewer viewer = new DiagramGraphicalViewer();
	viewer.setEditPartFactory(EditPartService.getInstance());
	viewer.createControl(parent);
	viewer.setRootEditPart(new DiagramRootEditPart(MeasurementUnit.PIXEL_LITERAL));
	viewer.setContents(diagram);
	return viewer;
}

@Override
public void createPartControl(Composite parent) {
	Composite c = new Composite(parent, SWT.NONE);
	c.setLayout(new RowLayout());
	for (int i = 0; i < 2; i++)
		createViewer(createDiagram(), c);
}
With this code I get 2 diagrams drawn on my view. With the line CSSHelper.installCSSSupport(resourceset); they also have the same appearance as when I'd open them in papyrus editor. Next step is to start a transaction to modify one of the models.

[Updated on: Mon, 19 August 2013 10:41]

Report message to a moderator

Previous Topic:How in the world do you generate a papyrus model from an existing uml?
Next Topic:changing .uml model file do not change .di model file
Goto Forum:
  


Current Time: Wed Sep 24 04:42:47 GMT 2014

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

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