Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » Graphiti » Create svg from diagram programmtically(Create SVG via methods problem)
Create svg from diagram programmtically [message #1738027] Fri, 15 July 2016 07:31 Go to next message
Brause Jochen is currently offline Brause JochenFriend
Messages: 3
Registered: July 2016
Junior Member
Hello community,
i would like to create a svg from my graphiti diagram in a programmatically way. But i couldnt find a good solution.

I tried several solutions but i wasnt able to run them in a proper way. Example: https://github.com/e2point718/graphiti-examples/blob/master/com.github.e2point718.eclipse.diagramview/src/com/github/e2point718/eclipse/diagramview/SaveGraphitiDiagramAsImage.java

In this example, i couldnt find the method convertDiagramToBytes in line 73.

GraphitiUi.getImageService().convertDiagramToBytes(diagram, SWT.IMAGE_JPEG);

Maybe replaced with another method or moved to another class? I couldnt find it -_-`. Does anybody has a good solution in mind to generate a svg / image?

Thx for your help.
Re: Create svg from diagram programmtically [message #1738472 is a reply to message #1738027] Wed, 20 July 2016 07:41 Go to previous messageGo to next message
Michael Wenz is currently offline Michael WenzFriend
Messages: 1899
Registered: July 2009
Location: Walldorf, Germany
Senior Member
Jochen,

unfortunately that does not come out of the box.

There is an example class for exporting diagram files in the examples.common plugin, but that will only directly work for the standard image formats that SWT supports (e.g. BMP, GIF, JPG). For details you can check the source code at:
http://git.eclipse.org/c/graphiti/org.eclipse.graphiti.git/tree/examples/org.eclipse.graphiti.examples.common/src/org/eclipse/graphiti/examples/common/handler/SaveDiagramAsImageHandler.java

The actual work is done in GraphitiUi.getImageService().convertDiagramToBytes which converts a diagram to an SWT imageand saves this data to a file. For your case you could build something similar, create an image from the diagram and pass it to Graphiti's org.eclipse.graphiti.export.batik.SVGExporter. An example how to use that is in org.eclipse.graphiti.ui.features.DefaultSaveImageFeature#getSaveAsImageOperationForNonStandardExporter.

HTH,
Michael

Re: Create svg from diagram programmtically [message #1738581 is a reply to message #1738472] Thu, 21 July 2016 06:38 Go to previous messageGo to next message
Brause Jochen is currently offline Brause JochenFriend
Messages: 3
Registered: July 2016
Junior Member
Hello Michael,

thx for your reply.

I tried to reuse the standard svg exporter and im surprised, that i used the same way you described. On the one hand, it works. I can generate an svg.
But now i have a problem with the svg it self. This exporter cuts the top and bottom figures of my diagram and some items on the left and right. In a summary:
There isnt the whole diagram visualize in the svg. Sad
See at the attchment: A picture and the svg....

The biggest problem is, that the standard exporter has the same problem.

If you could help me, to find out my error, that would be awesome.
Im no professionel programmer so be not so hard with my code Very Happy

This is my code from the standard exporter. I used exisiting code and created my own class.

package de.intervista.fmc.fmceditor.diagrameditor.ui.util;

import java.io.FileOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.SWTGraphics;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.editparts.LayerManager;
import org.eclipse.graphiti.internal.util.T;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.ui.editor.DiagramEditor;
import org.eclipse.graphiti.ui.internal.editor.GFFigureCanvas;
import org.eclipse.graphiti.ui.internal.fixed.FixedScaledGraphics;
import org.eclipse.graphiti.ui.internal.platform.ExtensionManager;
import org.eclipse.graphiti.ui.internal.services.GraphitiUiInternal;
import org.eclipse.graphiti.ui.internal.util.ui.print.DefaultPrintPreferences;
import org.eclipse.graphiti.ui.internal.util.ui.print.IDiagramsExporter;
import org.eclipse.graphiti.ui.saveasimage.ISaveAsImageConfiguration;
import org.eclipse.graphiti.ui.services.GraphitiUi;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;

    /**
     * The default feature implementation for saving a diagram as an image. This
     * feature is used to trigger saving from inside an open and initialized
     * {@link DiagramEditor}. It relies on an existing {@link GraphicalViewer}
     * showing the diagram to save.
     */
    @SuppressWarnings("restriction")
    public class SaveDiagramAsImage  {

        private static final String ERROR_MESSAGE_CANT_SAVE                  = "Cannot save image: ";
        private static final String ERROR_MESSAGE_CLOSE_OUTPUT_STREAM_FAILED = "close output stream failed";
        private static final String ERROR_MESSAGE_USER_CANCEL                = "Save as image operation was cancelled by user";
        private static final String FILE_EXTENSION_SVG = "svg";
        private static final String FILE_EXTENSION_JPG = "jpg";
        private static final String IMAGE_EXTENSION_SVG = "SVG";
        
        private static IResource diagramFile;
        private static String selectedImageExtension;
        private static int imageFormatExtension;
        
        private Image scaledImageToExport;
        private static GraphicalViewer graphicalViewer;
        
        /**
         * <code>_selectionFigure</code> represents a figure which corresponds to the selected EditPart.
         */
        private GraphicalEditPart selectedEditPart;
        /**
         * <code>allFigures</code> represents a figure that contains all printable layers.
         */
        private IFigure allFigures;
        /**
         * <code>selectionFigure</code> represents a figure which corresponds to the selected EditPart.
         */
        private IFigure selectionFigure;
        /**
         * <code>diagramFigures</code> corresponds either to the value of
         * <code>allFigures</code> or to the value of <code>_selectionFigure</code>
         */
        private IFigure diagramFigures;
        /**
         * Image corresponding to either one selected part of the diagram or the
         * whole diagram (scaled version)
         */
        private Image scaledImage;
        private Image imageAll;
        private Image image;
        private Image imageSelection;

        public SaveDiagramAsImage() {
            /* empty constructor */
        }

        /**
         * Performs the save as image operation. This implementation retrieves the {@link GraphicalViewer}
         * from the {@link DiagramEditor} itself, that already displays the diagram, queries for 
         * {@link ISaveAsImageConfiguration}.
         */
        public void save(IResource fileItem, String imageExtension) {
            
            addItems(fileItem, imageExtension);
            
            // get the graphical Viewer
            IWorkbenchPage currentWorkBench = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
            IEditorPart activeEditor        = currentWorkBench.getActiveEditor();

            graphicalViewer = null;
            
            if (activeEditor instanceof DiagramEditor) {
                DiagramEditor diagram = (DiagramEditor) activeEditor;
                
                // Get viewer containing the diagram to print (by default the one
                // contained in the diagram editor that starts this feature
                graphicalViewer = (GraphicalViewer) diagram.getAdapter(GraphicalViewer.class);
            }
            
            // Instead of saveAsImageConfiguration.getFigure() --> diagramFigures
            determinePossibleFigures();
            saveImageOperation();
        }

        private void addItems(IResource fileItem, String imageExtension) {
            
            diagramFile            = fileItem;
            selectedImageExtension = imageExtension;
            switch(imageExtension) {
            case "PNG":
                imageFormatExtension = SWT.IMAGE_PNG;
                break;
            case "JPG":
                imageFormatExtension = SWT.IMAGE_JPEG;
                break;
            default: // SVG:
                imageFormatExtension = 6;
                break;
            }
        }

        private void saveImageOperation() {

            if (diagramFile == null) {
                return;
            }
            String name     = StringUtils.substringBeforeLast(diagramFile.getName(), "."); 
            String filename = StringUtils.substringBeforeLast(diagramFile.getLocation().toString(), "/");
            filename       += "/" + name + "." + selectedImageExtension;

            if (filename != null) {
                Shell shell = GraphitiUiInternal.getWorkbenchService().getShell();
                try {
                    // Add extension to filename (if none exists)
                    filename = addFileExtension(filename);
                        
                    // Create the save as image operation ...
                    IRunnableWithProgress operation = getSaveAsImageOperation(filename);
                    
                    // ... and start save as image
                    new ProgressMonitorDialog(shell).run(false, false, operation);
                } catch (InterruptedException e) {
                    T.racer().warning(ERROR_MESSAGE_USER_CANCEL); //$NON-NLS-1$
                } catch (Exception e) {
                    String message = ERROR_MESSAGE_CANT_SAVE; //$NON-NLS-1$
                    MessageDialog.openError(shell, ERROR_MESSAGE_CANT_SAVE, message + e.getMessage()); //$NON-NLS-1$
                    T.racer().error(message, e);
                }
            }
        }

        /**
         * Adds the given file extension to the given filename.
         * 
         * @param extension - A string holding the extension.
         * @param filename - A string holding the filename.
         * @return - A string holding the filename plus the extension.
         */
        private String addFileExtension(String filename) {
            
            IPath path = new Path(filename);
            if (path.getFileExtension() == null) {
                return filename + "." + selectedImageExtension.toLowerCase();
            }
            return filename;
        }

        /**
         * Called to create the operation that is actually used for executing the
         * save as image functionality. The default implementation returns the
         * Graphiti default save as image operation that should be sufficient for
         * almost all use cases.
         * <p>
         * This method delegates to {@link #getSaveAsImageOperationForStandardImageExporter(String, int)}
         * to perform the save as image for the standard formats like GIF, JPG, BMP etc. and to 
         * {@link #getSaveAsImageOperationForNonStandardSVGExporter(String)} for the non standard exporters 
         * (registered via the Graphiti export image extension point) like SVG.

         * @param filename - The filename to use for saving the image
         * @return The operation that will be used to actually perform the save as
         *         image.
         */
        private IRunnableWithProgress getSaveAsImageOperation(final String filename) {
            
            IRunnableWithProgress operation = null;

            if (imageFormatExtension == SWT.IMAGE_PNG) {
                setScaledImage(getImageScaleFactor(), 100000.0d);
            } else {
                setScaledImage(getImageScaleFactor());
            }
            
            if (getDiagramExporters().containsKey(selectedImageExtension)) {
                // If the exporter is non-standard, i.e. registered via
                // extension point, we need to call the registered exporter.
                operation = getSaveAsImageOperationForNonStandardSVGExporter(filename);
            } else {
                // Handle internal image format.
                int extension = 0;
                if("JPG".equals(selectedImageExtension)) {
                    extension = SWT.IMAGE_JPEG;
                }
                if ("PNG".equals(selectedImageExtension)) {
                    extension = SWT.IMAGE_PNG;
                }
                operation = getSaveAsImageOperationForStandardImageExporter(filename, extension);
            }
            return operation;
        }
        
        private double getImageScaleFactor() {
            DefaultPrintPreferences preferences = new DefaultPrintPreferences();
            return preferences.getDoublePreference(DefaultPrintPreferences.SCALE_FACTOR);
        }
        
        /**
         * Called to create the operation that is actually used for executing the
         * save as image functionality for standard formats. The default
         * implementation returns the graphiti default save as image operation that
         * should be sufficient for almost all use cases.

         * @param filename - The filename to use for saving the image.
         * @return         - The operation that will be used to actually perform the 
         *                   save as image.
         */
        private IRunnableWithProgress getSaveAsImageOperationForNonStandardSVGExporter(final String filename) {
            
            final IDiagramsExporter exporter = ExtensionManager.getSingleton().getDiagramExporterForType(selectedImageExtension);
            Assert.isNotNull(exporter);
            return new IRunnableWithProgress() {

                @Override
                public void run(IProgressMonitor monitor) throws InvocationTargetException {
                    try {
                        double imageScaleFactor = getImageScaleFactor();
                        // Instead of saveAsImageConfiguration.getImageScaleFactor() --> imageScaleFactor                    
                        scaledImageToExport = scaledImage;
                        //Instead of saveAsImageConfiguration.getScaledImage() --> scaledImage
                        exporter.export(scaledImageToExport, diagramFigures, filename, imageScaleFactor);
                    } catch (Exception e) {
                        throw new InvocationTargetException(e);
                    }
                }
            };
            
        }

        /**
         * Called to create the operation that is actually used for executing the
         * save as image functionality for non-standard formats. The default
         * implementation returns the graphiti default save as image operation that
         * should be sufficient for almost all use cases.

         * @param filename - The filename to use for saving the image.
         * @return         - The operation that will be used to actually perform the 
         *                   save as image.
         */
        private IRunnableWithProgress getSaveAsImageOperationForStandardImageExporter(final String filename, int imageFormat) {
            
            //int imageFormat        = saveAsImageConfiguration.getImageFormat();
            //Image scaledImage = saveAsImageConfiguration.getScaledImage();
            scaledImageToExport = scaledImage;
            
            final byte[] imageBytes  = GraphitiUi.getImageService().convertImageToBytes(scaledImage, imageFormat);
            return new IRunnableWithProgress() {
                
                @Override
                public void run(IProgressMonitor monitor) throws InvocationTargetException {
                    FileOutputStream outputStream = null;
                    try {
                        outputStream = new FileOutputStream(filename);
                        outputStream.write(imageBytes);
                    } catch (Exception e) {
                        throw new InvocationTargetException(e);
                    } finally {
                        try {
                            outputStream.close();
                        } catch (Exception x) {
                            T.racer().error(ERROR_MESSAGE_CLOSE_OUTPUT_STREAM_FAILED, x); //$NON-NLS-1$
                        }
                    }
                }
            };

        }

        /**
         * Returns all available graphiti diagram exporters that are registered at
         * the according graphiti extension point. Note that the standard exporters
         * like GIF, JPG, BMP are not part of the returned ones.
         * 
         * @return A {@link Map} holding all exporters.
         */
        private Map<String, Boolean> getDiagramExporters() {
            return ExtensionManager.getSingleton().getDiagramExporterTypes();
        }
        
        /**
         * determine diagramFigures, selectionFigure and allFigures
         */
        private void determinePossibleFigures() {
            allFigures      = null;
            selectionFigure = null;
            diagramFigures  = null;

            // shrink canvas to minimal necessary dimensions
            org.eclipse.swt.widgets.Control control = graphicalViewer.getControl();
            if (control instanceof GFFigureCanvas) {
                GFFigureCanvas canvas = (GFFigureCanvas) control;
                canvas.regainSpace();
            }

            EditPart rootEditPart = graphicalViewer.getRootEditPart();
            if (!(rootEditPart instanceof GraphicalEditPart))
                return;

            // determine allFigures
            GraphicalEditPart graphicalRootEditPart = (GraphicalEditPart) rootEditPart;
            IFigure rootFigure = ((LayerManager) graphicalRootEditPart).getLayer(LayerConstants.PRINTABLE_LAYERS);
            if (rootFigure == null)
                return;

            allFigures = rootFigure;

            // determine selectionFigure
            @SuppressWarnings("unchecked")
            List<EditPart> listOfEditParts = graphicalViewer.getSelectedEditParts();
            for (EditPart selEditPart : listOfEditParts) {
                if (!(selEditPart instanceof GraphicalEditPart) || (selEditPart == graphicalViewer.getContents())) {
                    selectionFigure = null;
                    break;
                }
                selectedEditPart = (GraphicalEditPart) selEditPart;
                selectionFigure  = selectedEditPart.getFigure();
                break;
            }

            // determine diagramFigures
            diagramFigures = (selectionFigure == null) ? allFigures : selectionFigure;
        }
        
        // Use if creating PNG.
        private void setScaledImage(double scaleFactor) {
            setScaledImage(scaleFactor, 3000.0d);
        }
        
        private void setScaledImage(double scaleFactor, double upperBoundPixels) {
            cleanUp();
            imageAll    = null;
            scaledImage = null;
            image       = null;

            // create _imageAll based on _allFigure
            initImageAll(upperBoundPixels);
            // create _scaledImage based either on _allFigure or on _selectionFigure
            // use scaleFactor to determine scaled version
            initScaledImage(scaleFactor, upperBoundPixels);

            initImage();
        }
        
        private void cleanUp() {
            if (scaledImage != null)
                scaledImage.dispose();
            if (image != null)
                image.dispose();
            if (imageAll != null)
                imageAll.dispose();
            if (imageSelection != null)
                imageSelection.dispose();
        }
        
        private void initImage() {
            if (selectionFigure != null) {
                imageSelection = new Image(Display.getDefault(), selectionFigure.getBounds().width,
                                           selectionFigure.getBounds().height);
                GC gc = new GC(imageSelection);
                SWTGraphics graphics = new SWTGraphics(gc);

                graphics.translate(-selectionFigure.getBounds().x, - selectionFigure.getBounds().y);

                selectionFigure.paint(graphics);
                addRelatedEditParts(graphics, selectedEditPart);

                if (gc != null)
                    gc.dispose();
                if (graphics != null)
                    graphics.dispose();
                image = imageSelection;
            } else {
                if (imageAll != null) {
                    image = imageAll;
                } else {
                    image = null;
                }
            }
        }
        
        private void initImageAll(double upperBoundPixels) {
            
            int width  = allFigures.getBounds().width;
            int height = allFigures.getBounds().height;

            // check whether the dimensions of the image to be created would
            // be small enough to prevent runtime exceptions
            if (width <= upperBoundPixels && height <= upperBoundPixels) {
                imageAll = new Image(Display.getDefault(), width, height);
                GC gc    = new GC(imageAll);
                SWTGraphics graphics = new SWTGraphics(gc);

                /* move all figures into the positive region */
                EditPart contents = graphicalViewer.getContents();
                if (contents instanceof GraphicalEditPart) {
                    IFigure contentsFigure  = ((GraphicalEditPart) contents).getFigure();
                    Rectangle contentBounds = contentsFigure.getBounds();
                    graphics.translate(-contentBounds.x, -contentBounds.y);
                }

                allFigures.paint(graphics);

                if (gc != null)
                    gc.dispose();
                if (graphics != null)
                    graphics.dispose();
            } else {
                imageAll = null;
            }
        }
        
        private void initScaledImage(double scaleFactor, double upperBoundPixels) {
            {
                GC gc = null;
                FixedScaledGraphics graphics = null;

                if (!isFigureSelected()) {
                    // if the scale factor is too high, the operating system will
                    // not be able to provide a handle,
                    // because the Image would require too much space. "no more
                    // Handles"-Exception or "out of Memory" Error
                    // will be thrown
                    if (scaleFactor * allFigures.getBounds().width > upperBoundPixels
                            || scaleFactor * allFigures.getBounds().height > upperBoundPixels) {
                        scaleFactor = Math.min(upperBoundPixels / allFigures.getBounds().width, upperBoundPixels / allFigures.getBounds().height);
                    }

                    scaledImage = new Image(Display.getDefault(), 
                                             (int) (allFigures.getBounds().width * scaleFactor), 
                                             (int) (scaleFactor * allFigures.getBounds().height));
                    gc       = new GC(scaledImage);
                    graphics = new FixedScaledGraphics(new SWTGraphics(gc));

                    graphics.scale(scaleFactor);

                    /* move all figures into the positive region */
                    EditPart contents = graphicalViewer.getContents();
                    if (contents instanceof GraphicalEditPart) {
                        IFigure contentsFigure  = ((GraphicalEditPart) contents).getFigure();
                        Rectangle contentBounds = contentsFigure.getBounds();
                        graphics.translate(-contentBounds.x, -contentBounds.y);
                    }
                    allFigures.paint(graphics);
                    
                } else {
                    if (scaleFactor * selectionFigure.getBounds().width > upperBoundPixels
                            || scaleFactor * selectionFigure.getBounds().height > upperBoundPixels) {
                        scaleFactor = Math.min(upperBoundPixels / selectionFigure.getBounds().width, 
                                               upperBoundPixels / selectionFigure.getBounds().height);
                    }

                    scaledImage = new Image( null, (int) (selectionFigure.getBounds().width * scaleFactor),
                                             (int) (scaleFactor * selectionFigure.getBounds().height) );
                    gc       = new GC(scaledImage);
                    graphics = new FixedScaledGraphics(new SWTGraphics(gc));

                    graphics.scale(scaleFactor);
                    graphics.translate(-selectionFigure.getBounds().x, -selectionFigure.getBounds().y);

                    selectionFigure.paint(graphics);
                    addRelatedEditParts(graphics, selectedEditPart);

                }

                if (gc != null)
                    gc.dispose();
                if (graphics != null)
                    graphics.dispose();
            }
        }
        
        private void addRelatedEditParts(Graphics graphics, GraphicalEditPart ep) {
            
            List<EditPart> relatedEditParts = GraphitiUiInternal.getGefService().getConnectionsContainedInEditPart(ep);
            for (Object conn : relatedEditParts) {
                if (conn instanceof GraphicalEditPart) {
                    GraphicalEditPart conn2 = (GraphicalEditPart) conn;
                    if (conn2.getModel() instanceof PictogramElement) {
                        PictogramElement pe = (PictogramElement) conn2.getModel();
                        if (!pe.isVisible())
                            continue;

                        IFigure figure = conn2.getFigure();
                        figure.paint(graphics);
                    }
                }
            }
        }
        
        private boolean isFigureSelected() {
            return selectedEditPart != null;
        }
        
    }


  • Attachment: test_diag.SVG
    (Size: 16.17KB, Downloaded 175 times)
  • Attachment: pic.JPG
    (Size: 49.18KB, Downloaded 90 times)

[Updated on: Thu, 21 July 2016 07:03]

Report message to a moderator

Re: Create svg from diagram programmtically [message #1740113 is a reply to message #1738581] Tue, 09 August 2016 12:03 Go to previous message
Michael Wenz is currently offline Michael WenzFriend
Messages: 1899
Registered: July 2009
Location: Walldorf, Germany
Senior Member
Jochen,

at first glance this looks to me as if the exporter graps only the visible part of the diagram (the viewport) instead of the complete diagram. Could you double check that?

What do you mean with "the standard exporter has the same problem"? Do you mean the export functionality from within a Graphiti diagram or the export to standard format?

Michael
Previous Topic:Call for funding to release a new Graphiti extension for CDO under EPL !
Next Topic:Changing the colour of existing shapes (gradient start/stop?)
Goto Forum:
  


Current Time: Sun Nov 18 14:58:22 GMT 2018

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

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

Back to the top