ca0aed10fa08659c09d9f198a33da0ae5b222170
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / actions / ExportAllAction.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Vincent COUVERT
4  * Copyright (C) 2010 - DIGITEO - Clement DAVID
5  * Copyright (C) 2011-2015 - Scilab Enterprises - Clement DAVID
6  *
7  * Copyright (C) 2012 - 2016 - Scilab Enterprises
8  *
9  * This file is hereby licensed under the terms of the GNU GPL v2.0,
10  * pursuant to article 5.3.4 of the CeCILL v.2.1.
11  * This file was originally licensed under the terms of the CeCILL v2.1,
12  * and continues to be available under such terms.
13  * For more information, see the COPYING file which you should have received
14  * along with this program.
15  *
16  */
17
18 package org.scilab.modules.xcos.actions;
19
20 import java.awt.Color;
21 import java.awt.Toolkit;
22 import java.awt.event.ActionEvent;
23 import java.awt.image.BufferedImage;
24 import java.io.File;
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.Set;
30 import java.util.TreeSet;
31
32 import javax.imageio.ImageIO;
33 import javax.swing.JFileChooser;
34 import javax.swing.JOptionPane;
35
36 import org.scilab.modules.graph.ScilabGraph;
37 import org.scilab.modules.graph.actions.base.DefaultAction;
38 import org.scilab.modules.graph.utils.ScilabGraphRenderer;
39 import org.scilab.modules.gui.bridge.filechooser.FileMask;
40 import org.scilab.modules.gui.menuitem.MenuItem;
41 import org.scilab.modules.gui.messagebox.ScilabModalDialog;
42 import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption;
43 import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType;
44 import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType;
45 import org.scilab.modules.xcos.JavaController;
46 import org.scilab.modules.xcos.Kind;
47 import org.scilab.modules.xcos.ObjectProperties;
48 import org.scilab.modules.xcos.VectorOfScicosID;
49 import org.scilab.modules.xcos.XcosTab;
50 import org.scilab.modules.xcos.configuration.ConfigurationManager;
51 import org.scilab.modules.xcos.graph.XcosDiagram;
52 import org.scilab.modules.xcos.utils.XcosMessages;
53 import org.w3c.dom.Document;
54
55 import com.mxgraph.swing.mxGraphComponent;
56 import com.mxgraph.util.mxCellRenderer;
57 import com.mxgraph.util.mxUtils;
58 import com.mxgraph.util.mxXmlUtils;
59
60 /**
61  * Diagram export management
62  */
63 @SuppressWarnings(value = { "serial" })
64 public final class ExportAllAction extends DefaultAction {
65     /** Name of the action */
66     public static final String NAME = XcosMessages.EXPORT_ALL;
67     /** Icon name of the action */
68     public static final String SMALL_ICON = "";
69     /** Mnemonic key of the action */
70     public static final int MNEMONIC_KEY = 0;
71     /** Accelerator key for the action */
72     public static final int ACCELERATOR_KEY = Toolkit.getDefaultToolkit()
73             .getMenuShortcutKeyMask();
74
75     private static final String HTML = "html";
76     private static final String VML = "vml";
77     private static final String SVG = "svg";
78
79     private boolean useBackground = true;
80
81     /**
82      * Constructor
83      *
84      * @param scilabGraph
85      *            associated Scilab Graph
86      */
87     public ExportAllAction(ScilabGraph scilabGraph) {
88         super(scilabGraph);
89     }
90
91     /**
92      * Create export menu
93      *
94      * @param scilabGraph
95      *            associated Scilab Graph
96      * @return the menu
97      */
98     public static MenuItem createMenu(ScilabGraph scilabGraph) {
99         return createMenu(scilabGraph, ExportAllAction.class);
100     }
101
102     /**
103      * Action !!!
104      *
105      * @param e
106      *            parameter
107      * @see org.scilab.modules.graph.actions.base.DefaultAction#actionPerformed(java.awt.event.ActionEvent)
108      */
109     @Override
110     public void actionPerformed(ActionEvent e) {
111         final XcosDiagram graph = ((XcosDiagram) getGraph(null)).getRootDiagram();
112
113         // Adds a filter for each supported image format
114         Collection<String> imageFormats = Arrays.asList(ImageIO.getWriterFileSuffixes());
115
116         // The mask ordered collection
117         Set<String> mask = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
118
119         mask.add(SVG);
120         mask.add(HTML);
121         mask.add(VML);
122         mask.addAll(imageFormats);
123
124         JFileChooser fc = new JFileChooser();
125         fc.setDialogTitle(XcosMessages.EXPORT_ALL + XcosMessages.DOTS);
126         fc.setApproveButtonText(XcosMessages.EXPORT);
127         fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
128
129         fc.setAcceptAllFileFilterUsed(false);
130         for (String string : mask) {
131             fc.addChoosableFileFilter(new FileMask(string, string.toUpperCase()));
132         }
133
134         ConfigurationManager.configureCurrentDirectory(fc);
135
136         int selection = fc.showSaveDialog(getGraph(null).getAsComponent());
137         if (selection == JFileChooser.APPROVE_OPTION) {
138             File dir = fc.getSelectedFile();
139
140             /* getting the format */
141             String format = ((FileMask) fc.getFileFilter()).getExtensionFromFilter();
142
143             /* update states from the format */
144             if ((!format.equalsIgnoreCase("png"))
145                     || ScilabModalDialog.show(XcosTab.get((XcosDiagram) getGraph(null)),
146                                               XcosMessages.TRANSPARENT_BACKGROUND, XcosMessages.XCOS,
147                                               IconType.QUESTION_ICON, ButtonType.YES_NO) != AnswerOption.YES_OPTION) {
148                 useBackground = true;
149             }
150
151             /*
152              * Instantiate all the sub-diagrams
153              */
154             JavaController controller = new JavaController();
155             ArrayList<XcosDiagram> diagrams = new ArrayList<>();
156             diagrams.add(graph);
157
158             ArrayList<Long> stash = new ArrayList<>();
159             allocateDiagrams(controller, diagrams, stash, graph.getUID(), Kind.DIAGRAM);
160             while (!stash.isEmpty()) {
161                 final long uid = stash.remove(stash.size() - 1);
162                 allocateDiagrams(controller, diagrams, stash, uid, Kind.BLOCK);
163             }
164
165             /*
166              * Export
167              */
168             try {
169                 export(graph, new File(dir, graph.getTitle() + "." + format), format);
170
171                 for (XcosDiagram d : diagrams) {
172                     export(d, new File(dir, d.getTitle() + "." + format), format);
173                 }
174             } catch (IOException e1) {
175                 e1.printStackTrace();
176             }
177
178         }
179     }
180
181     private void allocateDiagrams(JavaController controller, ArrayList<XcosDiagram> diagrams, ArrayList<Long> stash,
182                                   final long uid, final Kind kind) {
183         final VectorOfScicosID children = new VectorOfScicosID();
184         controller.getObjectProperty(uid, kind, ObjectProperties.CHILDREN, children);
185
186         final int len = children.size();
187         for (int i = 0; i < len ; i++) {
188             String[] interfaceFunction = new String[1];
189             long currentUID = children.get(i);
190             if (controller.getKind(currentUID) == Kind.BLOCK) {
191                 controller.getObjectProperty(children.get(i), Kind.BLOCK, ObjectProperties.INTERFACE_FUNCTION, interfaceFunction);
192                 if (!"SUPER_f".equals(interfaceFunction[0])) {
193                     continue;
194                 }
195
196
197                 if (diagrams.stream().noneMatch(d -> d.getUID() == currentUID)) {
198                     String[] strUID = new String[1];
199                     controller.getObjectProperty(currentUID, Kind.BLOCK, ObjectProperties.UID, strUID);
200
201                     final XcosDiagram child = new XcosDiagram(controller, currentUID, Kind.BLOCK, strUID[0]);
202                     diagrams.add(child);
203                     stash.add(currentUID);
204                 }
205             }
206
207         }
208     }
209
210     /**
211      * Export the graph into the filename.
212      *
213      * The filename extension is used find export format.
214      *
215      * @param graph
216      *            the current graph
217      * @param filename
218      *            the filename
219      * @param fileFormat
220      *            the format to save
221      * @throws IOException
222      *             when a write problem occurs.
223      */
224     private void export(XcosDiagram graph, File filename, String fileFormat)
225     throws IOException {
226         filename.getParentFile().mkdirs();
227
228         if (fileFormat.equalsIgnoreCase(SVG)) {
229             ScilabGraphRenderer.createSvgDocument(graph, null, 1, null, null,
230                                                   filename.getCanonicalPath());
231         } else if (fileFormat.equalsIgnoreCase(VML)) {
232             Document doc = mxCellRenderer.createVmlDocument(graph, null, 1,
233                            null, null);
234             if (doc != null) {
235                 mxUtils.writeFile(mxXmlUtils.getXml(doc.getDocumentElement()),
236                                   filename.getCanonicalPath());
237             }
238         } else if (fileFormat.equalsIgnoreCase(HTML)) {
239             Document doc = mxCellRenderer.createHtmlDocument(graph, null, 1,
240                            null, null);
241             if (doc != null) {
242                 mxUtils.writeFile(mxXmlUtils.getXml(doc.getDocumentElement()),
243                                   filename.getCanonicalPath());
244             }
245         } else {
246             exportBufferedImage(graph, filename, fileFormat);
247         }
248     }
249
250     /**
251      * Use the Java image capabilities to export the diagram
252      *
253      * @param graph
254      *            the current diagram
255      * @param filename
256      *            the current filename
257      * @param fileFormat
258      *            the file format
259      * @throws IOException
260      *             when an error occurs
261      */
262     private void exportBufferedImage(XcosDiagram graph, File filename,
263                                      String fileFormat) throws IOException {
264         final mxGraphComponent graphComponent = graph.getAsComponent();
265
266         Color bg = null;
267
268         if (useBackground) {
269             bg = graphComponent.getBackground();
270         }
271
272         BufferedImage image = mxCellRenderer.createBufferedImage(graph, null,
273                               1, bg, graphComponent.isAntiAlias(), null,
274                               graphComponent.getCanvas());
275
276         if (image != null) {
277             ImageIO.write(image, fileFormat, filename);
278         } else {
279             JOptionPane.showMessageDialog(graphComponent,
280                                           XcosMessages.NO_IMAGE_DATA);
281         }
282     }
283 }