GEF5 export to SVG [message #1778877] |
Fri, 22 December 2017 15:22  |
Eclipse User |
|
|
|
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 #1779513 is a reply to message #1778888] |
Mon, 08 January 2018 18:42   |
Eclipse User |
|
|
|
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 18:43] by Moderator
|
|
|
Re: GEF5 export to SVG [message #1785405 is a reply to message #1779513] |
Fri, 13 April 2018 09:47  |
Eclipse User |
|
|
|
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
|
|
|
Powered by
FUDForum. Page generated in 0.03525 seconds