]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFDiagramExportWizard.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / pdf / PDFDiagramExportWizard.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.modeling.ui.pdf;\r
13 \r
14 import java.io.IOException;\r
15 import java.lang.reflect.InvocationTargetException;\r
16 import java.util.ArrayList;\r
17 import java.util.Collection;\r
18 import java.util.Collections;\r
19 import java.util.Deque;\r
20 import java.util.Iterator;\r
21 import java.util.LinkedList;\r
22 import java.util.List;\r
23 import java.util.Set;\r
24 import java.util.TreeSet;\r
25 \r
26 import org.eclipse.core.runtime.IProgressMonitor;\r
27 import org.eclipse.core.runtime.preferences.InstanceScope;\r
28 import org.eclipse.jface.dialogs.MessageDialog;\r
29 import org.eclipse.jface.operation.IRunnableWithProgress;\r
30 import org.eclipse.jface.preference.IPersistentPreferenceStore;\r
31 import org.eclipse.jface.preference.IPreferenceStore;\r
32 import org.eclipse.jface.viewers.IFilter;\r
33 import org.eclipse.jface.viewers.IStructuredSelection;\r
34 import org.eclipse.jface.wizard.Wizard;\r
35 import org.eclipse.ui.IExportWizard;\r
36 import org.eclipse.ui.IMemento;\r
37 import org.eclipse.ui.IWorkbench;\r
38 import org.eclipse.ui.preferences.ScopedPreferenceStore;\r
39 import org.simantics.Simantics;\r
40 import org.simantics.browsing.ui.graph.impl.request.GetName;\r
41 import org.simantics.db.ReadGraph;\r
42 import org.simantics.db.Resource;\r
43 import org.simantics.db.common.NamedResource;\r
44 import org.simantics.db.common.request.ObjectsWithType;\r
45 import org.simantics.db.common.request.ReadRequest;\r
46 import org.simantics.db.exception.DatabaseException;\r
47 import org.simantics.db.layer0.request.ActiveModels;\r
48 import org.simantics.db.management.ISessionContext;\r
49 import org.simantics.layer0.Layer0;\r
50 import org.simantics.modeling.requests.Node;\r
51 import org.simantics.modeling.ui.Activator;\r
52 import org.simantics.modeling.ui.utils.NoProjectPage;\r
53 import org.simantics.project.IProject;\r
54 import org.simantics.project.ProjectKeys;\r
55 import org.simantics.simulation.ontology.SimulationResource;\r
56 import org.simantics.ui.SimanticsUI;\r
57 import org.simantics.ui.utils.ResourceAdaptionUtils;\r
58 import org.simantics.utils.FileUtils;\r
59 import org.simantics.utils.ui.ErrorLogger;\r
60 import org.simantics.utils.ui.ExceptionUtils;\r
61 import org.simantics.utils.ui.workbench.StringMemento;\r
62 \r
63 public class PDFDiagramExportWizard extends Wizard implements IExportWizard {\r
64 \r
65     private static final int    MAX_RECENT_EXPORT_PATHS = 10;\r
66 \r
67     private static final String TAG_PATH  = "path";\r
68 \r
69     private static final String ATTR_NAME = "name";\r
70 \r
71     Deque<String>               recentExportPaths;\r
72     boolean                     zoomToFit;\r
73     boolean                                             attachTG, attachWiki;\r
74 \r
75     PDFExportPlan              exportPlan;\r
76 \r
77     private boolean readPreferences() {\r
78         IPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, Activator.PLUGIN_ID);\r
79 \r
80         String recentPathsPref = store.getString(Preferences.DIAGRAM_EXPORT_PDF_PATH);\r
81         recentExportPaths = decodePaths(recentPathsPref);\r
82         zoomToFit = store.getBoolean(Preferences.DIAGRAM_EXPORT_PDF_ZOOM_TO_FIT);\r
83         attachTG =  store.getBoolean(Preferences.DIAGRAM_EXPORT_PDF_ATTACH_TG);\r
84         attachWiki =  store.getBoolean(Preferences.DIAGRAM_EXPORT_PDF_ATTACH_WIKI);\r
85 \r
86         return true;\r
87     }\r
88 \r
89     private void writePreferences() throws IOException {\r
90         IPersistentPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, Activator.PLUGIN_ID);\r
91 \r
92         store.putValue(Preferences.DIAGRAM_EXPORT_PDF_PATH, encodePaths(recentExportPaths));\r
93         store.putValue(Preferences.DIAGRAM_EXPORT_PDF_ZOOM_TO_FIT, String.valueOf(zoomToFit));\r
94         store.putValue(Preferences.DIAGRAM_EXPORT_PDF_ATTACH_TG, String.valueOf(attachTG));\r
95         store.putValue(Preferences.DIAGRAM_EXPORT_PDF_ATTACH_WIKI, String.valueOf(attachWiki));\r
96 \r
97         if (store.needsSaving())\r
98             store.save();\r
99     }\r
100 \r
101     private Deque<String> decodePaths(String recentPathsPref) {\r
102         Deque<String> result = new LinkedList<String>();\r
103         try {\r
104             StringMemento sm = new StringMemento(recentPathsPref);\r
105             for (IMemento m : sm.getChildren(TAG_PATH)) {\r
106                 String name = m.getString(ATTR_NAME);\r
107                 if (name != null && !name.isEmpty())\r
108                     result.add(name);\r
109             }\r
110         } catch (IllegalArgumentException e) {\r
111         }\r
112         return result;\r
113     }\r
114 \r
115     private String encodePaths(Deque<String> recentPaths) {\r
116         StringMemento sm = new StringMemento();\r
117         for (String path : recentPaths) {\r
118             IMemento m = sm.createChild(TAG_PATH);\r
119             m.putString(ATTR_NAME, path);\r
120         }\r
121         return sm.toString();\r
122     }\r
123 \r
124     public PDFDiagramExportWizard() {\r
125         setWindowTitle("Export Diagrams to PDF");\r
126         setNeedsProgressMonitor(true);\r
127     }\r
128 \r
129     @Override\r
130     public void addPages() {\r
131         super.addPages();\r
132         if (exportPlan != null) {\r
133             addPage(new PDFExportPage(exportPlan));\r
134         } else {\r
135             addPage(new NoProjectPage("Export Diagrams to PDF"));\r
136         }\r
137     }\r
138 \r
139     private NamedResource toNamedResource(ReadGraph graph, Resource r) throws DatabaseException {\r
140         String name = graph.syncRequest(new GetName(r));\r
141         return new NamedResource(name, r);\r
142     }\r
143 \r
144     @Override\r
145     public void init(IWorkbench workbench, IStructuredSelection selection) {\r
146         readPreferences();\r
147 \r
148         ISessionContext ctx = SimanticsUI.getSessionContext();\r
149         if (ctx == null)\r
150             return;\r
151         IProject project = ctx.getHint(ProjectKeys.KEY_PROJECT);\r
152         if (project == null)\r
153             return;\r
154 \r
155         exportPlan = new PDFExportPlan(ctx, recentExportPaths);\r
156         exportPlan.project = project;\r
157         final Object selectedObject = selection.getFirstElement();\r
158         exportPlan.fitContentToPageMargins = zoomToFit;\r
159         exportPlan.attachTG = attachTG;\r
160         exportPlan.attachWiki = attachWiki;\r
161         \r
162         // Get all model names\r
163         try {\r
164             exportPlan.sessionContext.getSession().syncRequest(new ReadRequest() {\r
165                 @Override\r
166                 public void run(ReadGraph graph) throws DatabaseException {\r
167                     Resource selection = ResourceAdaptionUtils.toSingleResource(selectedObject);\r
168                     if (selection != null) {\r
169                         //exportModel.selection = new NamedResource(name + " (input selection)", selection);\r
170                         exportPlan.selection = toNamedResource(graph, selection);\r
171                         exportPlan.selectableModels.add(exportPlan.selection);\r
172                     } else {\r
173                         for (Resource activeModel : graph.syncRequest(new ActiveModels(exportPlan.project.get()))) {\r
174                             selection = activeModel;\r
175                             exportPlan.selection = toNamedResource(graph, activeModel);\r
176                             exportPlan.selectableModels.add( exportPlan.selection );\r
177                             break;\r
178                         }\r
179                     }\r
180 \r
181                     List<NamedResource> models = new ArrayList<NamedResource>();\r
182                     \r
183                     Collection<Resource> ontologies = Simantics.applySCL("Simantics/SharedOntologies", "traverseSharedOntologies", graph, graph.getRootLibrary());\r
184                     for (Resource model : ontologies) {\r
185                         if (model.equals(selection))\r
186                             continue;\r
187                         models.add( toNamedResource(graph, model) );\r
188                     }\r
189                     \r
190                     for (Resource model : graph.syncRequest(new ObjectsWithType(exportPlan.project.get(),\r
191                             Layer0.getInstance(graph).ConsistsOf, SimulationResource.getInstance(graph).Model))) {\r
192                         if (model.equals(selection))\r
193                             continue;\r
194                         models.add( toNamedResource(graph, model) );\r
195                     }\r
196                     Collections.sort(models);\r
197                     exportPlan.selectableModels.addAll(models);\r
198                     if (selection == null && !exportPlan.selectableModels.isEmpty()) {\r
199                         exportPlan.selection = exportPlan.selectableModels.get(0);\r
200                     }\r
201                 }\r
202             });\r
203         } catch (DatabaseException e) {\r
204             e.printStackTrace();\r
205         }\r
206     }\r
207 \r
208     @Override\r
209     public boolean performFinish() {\r
210         if (exportPlan.exportLocation.exists()) {\r
211             boolean confirmed = MessageDialog.openConfirm(getShell(), "Overwrite", "Are you sure you want to overwrite " + exportPlan.exportLocation);\r
212             if (!confirmed)\r
213                 return false;\r
214 \r
215             try {\r
216                 FileUtils.deleteAll(exportPlan.exportLocation);\r
217             } catch (IOException e) {\r
218                 ExceptionUtils.logAndShowError(e);\r
219                 return false;\r
220             }\r
221         }\r
222 \r
223         try {\r
224             recentExportPaths.addFirst(exportPlan.exportLocation.getAbsolutePath());\r
225 \r
226             // Remove duplicates\r
227             Set<String> dups = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);\r
228             for (Iterator<String> it = recentExportPaths.iterator(); it.hasNext();) {\r
229                 String path = it.next();\r
230                 if (!dups.add(path)) {\r
231                     it.remove();\r
232                 }\r
233             }\r
234 \r
235             if (recentExportPaths.size() > MAX_RECENT_EXPORT_PATHS)\r
236                 recentExportPaths.pollLast();\r
237 \r
238             zoomToFit = exportPlan.fitContentToPageMargins;\r
239             attachTG = exportPlan.attachTG;\r
240             attachWiki = exportPlan.attachWiki;\r
241 \r
242             writePreferences();\r
243         } catch (IOException e) {\r
244             ErrorLogger.defaultLogError("Failed to write preferences", e);\r
245         }\r
246 \r
247         // Make sure that the diagrams are printed in the same order as the user\r
248         // saw them in the wizard.\r
249         exportPlan.selectedNodes = exportPlan.nodes.depthFirstFlatten(new IFilter() {\r
250             @Override\r
251             public boolean select(Object toTest) {\r
252                 Node n = (Node) toTest;\r
253                 return exportPlan.selectedNodeSet.contains(n) && n.getDiagramResource() != null;\r
254             }\r
255         }, Node.CASE_INSENSITIVE_COMPARATOR);\r
256 \r
257         long start = System.currentTimeMillis();\r
258         try {\r
259             getContainer().run(true, true, new IRunnableWithProgress() {\r
260                 @Override\r
261                 public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {\r
262                     try {\r
263                         // Print pdf\r
264                         DiagramPrinter.printToPdf(monitor, exportPlan, exportPlan.exportLocation.toString(), exportPlan.selectedNodes, exportPlan.sessionContext);\r
265                         \r
266                     } catch (PdfException e) {\r
267                         throw new InvocationTargetException(e);\r
268                     } finally {\r
269                         monitor.done();\r
270                     }\r
271                 }\r
272             });\r
273         } catch (InvocationTargetException e) {\r
274             Throwable t = e.getTargetException();\r
275             ExceptionUtils.logAndShowError(t);\r
276             return false;\r
277         } catch (InterruptedException e) {\r
278             return false;\r
279         }\r
280         long end = System.currentTimeMillis();\r
281         System.out.println("PDF export took " + ((end - start) * 1e-3) + " seconds.");\r
282 \r
283         return true;\r
284     }\r
285 \r
286 }\r