Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » GEF » GEF5 export to SVG
GEF5 export to SVG [message #1778877] Fri, 22 December 2017 20:22 Go to next message
Ken Keefe is currently offline Ken KeefeFriend
Messages: 38
Registered: September 2009
Member
I'm trying to get an SVG export working on my GEF5 app. Since I can't publish my app's code, I thought I would try to get it working on the final Itemis Mind Map code on github. I've forked the project and added a simple button that calls the SVGExportHandler class in my com.itemis.gef.tutorial.mindmap package. Right now, the handler just creates an empty SVG file in the user's home directory.

One important constraint for what I'm trying to do is that I don't want to have to display the canvas and diagram before exporting it. I would like to simply hand the handler the model and SVGGraphics2D objects. What this means is that changes made to the diagram in the tutorial won't appear in the exported SVG. This is intentional.

Any advice on where to go from here?

Here is the mind map fork: https://github.com/kenjkeefe/gef-mindmap-tutorial
Re: GEF5 export to SVG [message #1778888 is a reply to message #1778877] Fri, 22 December 2017 23:29 Go to previous messageGo to next message
Ken Keefe is currently offline Ken KeefeFriend
Messages: 38
Registered: September 2009
Member
I think I am making progress, but I am hung up on a problem in
org.eclipse.gef.mvc.fx.parts.ITransformableContentPart.setVisualTransform(Affine).
It stems from the fact that the rootPart I create at SVGExportHandler:44
does not contain the adapters necessary for setVisualTransform. I can't
figure out how to set the adapters in the part.

I am guessing those adapters live in the domain, but I don't see how they get loaded into the SimpleMindMapPart. I've looked at how it is done with the displayed parts and the adapters for SimpleMindMapPart get loaded when it is added as a child of a LayeredRootPart. I can't figure out the right way to create a LayeredRootPart and load it with the adapters either.

Re: GEF5 export to SVG [message #1779513 is a reply to message #1778888] Mon, 08 January 2018 23:42 Go to previous messageGo to next message
Ken Keefe is currently offline Ken KeefeFriend
Messages: 38
Registered: September 2009
Member
Please help with this problem! I've been killing myself trying to dig through the code. I will say that DI is nice for writing concise code, but it is super brittle and hard to debug if you don't use code exactly the way it was intended.

Here are the problems I'm facing (using the latest commit in https://github.com/kenjkeefe/gef-mindmap-tutorial):

1. When I try to execute an export, I get an NPE at ITransformableContentPart.setVisualTransform() because getAdapter(TRANSFORM_PROVIDER_KEY) returns null. This is caused by the fact that the collection of adapters in the a part's AdaptableSupport is empty.

As near as I can tell, the adapter collection in AdaptableSupport should be populated when the MindMapNodePart is added to the LayeredRootPart. Which leads to...

2. I am unable to correctly create a LayeredRootPart. I cannot figure out how the GEF.MVC.FX code is doing it because I think it is being created by injection, and that code is incredibly difficult to decipher. If I could create a LayeredRootPart right, I think problem 1 would resolve itself.

Here is the export handler as it stands in the github repo. The createImageFromModel method is where things go off the rails. I want to be able to generate an image directly from a model without having to display the image on the screen. To do this, I created a separate module, domain, injector, scene, etc. I am guessing that this is where I am doing something wrong. Please help! Thanks!

public class SVGExportHandler {

	public SVGExportHandler() {
	}

	private Bounds createImageFromModel(SimpleMindMap mindMap, SVGGraphics2D svgGenerator) {
		SimpleMindMapModule module = new SimpleMindMapModule();
		Injector injector = Guice.createInjector(module);
		IDomain domain = injector.getInstance(IDomain.class);
		Parent canvas = domain.getAdapter(AdapterKey.get(IViewer.class, IDomain.CONTENT_VIEWER_ROLE)).getCanvas();
		new Scene(canvas);
		domain.activate();

		MindMapPartsFactory partsFactory = injector.getInstance(MindMapPartsFactory.class);

		IContentPart<? extends Node> rootPart = partsFactory.createContentPart(mindMap, null);
		rootPart.setContent(mindMap);
		loadDescenantParts(rootPart, partsFactory);

		Bounds size = rootPart.getVisual().getLayoutBounds();

		return size;
	}

	public void execute() {
		String homeDir = System.getProperty("user.home");
		final File svgFile = new File(homeDir, "export.svg");

		DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();

		Document document = domImpl.createDocument(null, "svg", null);

		try {
			OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(svgFile), "UTF-8");
			SVGGraphics2D svgGenerator = new SVGGraphics2D(document);

			// I want to show how to do this creation directly from a new model separate
			// from anything currently displayed visually.
			SimpleMindMapExampleFactory fac = new SimpleMindMapExampleFactory();
			SimpleMindMap mindMap = fac.createComplexExample();
			Bounds size = createImageFromModel(mindMap, svgGenerator);

			Element root = svgGenerator.getRoot();

			root.setAttributeNS(null, "width", Double.toString(size.getWidth()));
			root.setAttributeNS(null, "height", Double.toString(size.getHeight()));

			svgGenerator.stream(root, out);
			out.close();

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// There has to be a better GEF5 way of doing this...
	private void loadDescenantParts(IContentPart<? extends Node> part, MindMapPartsFactory partsFactory) {
		for (Object child : part.getContentChildrenUnmodifiable()) {
			IContentPart<? extends Node> childPart = partsFactory.createContentPart(child, null);
			childPart.setContent(child);
			part.addChild(childPart);
			loadDescenantParts(childPart, partsFactory);
		}
	}

}

[Updated on: Mon, 08 January 2018 23:43]

Report message to a moderator

Re: GEF5 export to SVG [message #1785405 is a reply to message #1779513] Fri, 13 April 2018 13:47 Go to previous message
Matthias Wienand is currently offline Matthias WienandFriend
Messages: 230
Registered: March 2015
Senior Member
Hi Ken,

first of all, you should not have to set adapters by yourself. Instead, the module should configure the adapters.

Secondly, you should not create the parts in-place, but rather have a viewer and set its contents. The synchronisation will create all content parts for you.

You should try with the same setup that you use for the mind map application.

W.r.t. LayeredRootPart, the root part is configured to be registered as an adapter for a viewer. You can see this inside the module configuration, for example, within MvcFxModule, there is a method bindRootPartAsContentViewerAdapter() that establishes a binding to IRootPart, which is resolved by the method bindIRootPart() that binds IRootPart to LayeredRootPart.

h2h
Matthias
Previous Topic:GEF and OpenJDK on RHEL
Next Topic:gef5 SimpleMindMapApplication with virtual nodes
Goto Forum:
  


Current Time: Mon Oct 07 00:03:59 GMT 2024

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

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

Back to the top