1 package org.simantics.charts.export;
\r
3 import java.awt.Graphics2D;
\r
4 import java.awt.geom.Rectangle2D;
\r
5 import java.util.ArrayList;
\r
6 import java.util.Collection;
\r
7 import java.util.Collections;
\r
8 import java.util.List;
\r
9 import java.util.UUID;
\r
11 import org.eclipse.core.runtime.IProgressMonitor;
\r
12 import org.eclipse.core.runtime.OperationCanceledException;
\r
13 import org.eclipse.core.runtime.preferences.DefaultScope;
\r
14 import org.eclipse.core.runtime.preferences.InstanceScope;
\r
15 import org.osgi.service.prefs.Preferences;
\r
16 import org.simantics.Simantics;
\r
17 import org.simantics.charts.preference.ChartPreferences;
\r
18 import org.simantics.charts.query.MilestoneSpecQuery;
\r
19 import org.simantics.charts.query.TrendSpecQuery;
\r
20 import org.simantics.databoard.Accessors;
\r
21 import org.simantics.databoard.accessor.RecordAccessor;
\r
22 import org.simantics.databoard.accessor.error.AccessorConstructionException;
\r
23 import org.simantics.databoard.accessor.reference.ChildReference;
\r
24 import org.simantics.databoard.binding.mutable.Variant;
\r
25 import org.simantics.databoard.type.RecordType;
\r
26 import org.simantics.databoard.type.UnionType;
\r
27 import org.simantics.db.Resource;
\r
28 import org.simantics.db.exception.DatabaseException;
\r
29 import org.simantics.db.layer0.request.PossibleModel;
\r
30 import org.simantics.export.core.ExportContext;
\r
31 import org.simantics.export.core.error.ExportException;
\r
32 import org.simantics.export.core.manager.Content;
\r
33 import org.simantics.export.core.pdf.ExportPdfWriter;
\r
34 import org.simantics.export.core.pdf.ExportPdfWriter.Page;
\r
35 import org.simantics.export.core.util.ExportQueries;
\r
36 import org.simantics.export.core.util.ExporterUtils;
\r
37 import org.simantics.g2d.canvas.impl.CanvasContext;
\r
38 import org.simantics.history.History;
\r
39 import org.simantics.history.HistoryException;
\r
40 import org.simantics.history.HistoryManager;
\r
41 import org.simantics.simulation.experiment.IExperiment;
\r
42 import org.simantics.simulation.experiment.IHistoryExperiment;
\r
43 import org.simantics.simulation.export.ExperimentExportClass;
\r
44 import org.simantics.simulation.project.ExperimentManager;
\r
45 import org.simantics.simulation.project.IExperimentManager;
\r
46 import org.simantics.trend.TrendInitializer;
\r
47 import org.simantics.trend.configuration.ItemPlacement;
\r
48 import org.simantics.trend.configuration.TimeFormat;
\r
49 import org.simantics.trend.configuration.TrendSpec;
\r
50 import org.simantics.trend.impl.MilestoneSpec;
\r
51 import org.simantics.trend.impl.TrendNode;
\r
52 import org.simantics.utils.datastructures.MapList;
\r
53 import org.simantics.utils.format.ValueFormat;
\r
54 import org.simantics.utils.threads.ThreadUtils;
\r
55 import org.simantics.utils.threads.WorkerThread;
\r
57 public class ExportChartPDF extends ExperimentExportClass {
\r
59 public static final RecordType chartOptions;
\r
61 public static String S_CHART = "Chart";
\r
62 public static ChildReference P_ITEMPLACEMENT = ChildReference.parsePath(S_CHART+"/Item Placement");
\r
63 public static ChildReference P_TIMEFORMAT = ChildReference.parsePath(S_CHART+"/Time Format");
\r
64 public static ChildReference P_VALUEFORMAT = ChildReference.parsePath(S_CHART+"/Value Format");
\r
67 chartOptions = new RecordType();
\r
68 chartOptions.addComponent("Item Placement", UnionType.newEnum("Stacked", "Overlapping"));
\r
69 chartOptions.addComponent("Time Format", UnionType.newEnum("Decimal", "Time"));
\r
70 chartOptions.addComponent("Value Format", UnionType.newEnum("Currency", "Scientific", "Engineering", "Default"));
\r
74 public void export(List<Content> contents,
\r
78 IProgressMonitor monitor,
\r
79 MapList<Content, Content> attachmentMap
\r
80 ) throws ExportException {
\r
82 // Flush all experiments, just in case.
\r
83 IExperimentManager em = Simantics.getProject().getHint( ExperimentManager.KEY_EXPERIMENT_MANAGER );
\r
85 for (IExperiment exp : em.getExperiments()) {
\r
86 if ( exp instanceof IHistoryExperiment ) {
\r
87 IHistoryExperiment he = (IHistoryExperiment) exp;
\r
90 } catch (HistoryException e) {
\r
96 final ExportPdfWriter writer = (ExportPdfWriter) handle;
\r
97 final WorkerThread workerThread = new WorkerThread("Chart PDF Painter");
\r
98 workerThread.start();
\r
101 final RecordAccessor ra = Accessors.getAccessor( options );
\r
103 // Get a list of the history managers the user has selected.
\r
104 List<ModelRef> modelRefs = ExperimentExportClass.getResult(ctx, options, true);
\r
105 List<ChartSettings> charts = new ArrayList<ChartSettings>();
\r
107 for ( Content content : contents ) {
\r
108 if (monitor.isCanceled())
\r
109 throw new OperationCanceledException();
\r
111 Resource chartRes = ctx.session.syncRequest( ExportQueries.toResource(content.url) );
\r
112 Resource model = ctx.session.syncRequest( new PossibleModel( chartRes ) );
\r
113 for (ModelRef modelRef : modelRefs) {
\r
114 if ( !modelRef.resource.equals(model) ) continue;
\r
115 for (ExperimentRef experimentRef : modelRef.experiments) {
\r
116 for (RunRef runRef : experimentRef.runs) {
\r
117 if ( runRef.historyFolder == null || !runRef.historyFolder.exists() ) continue;
\r
118 HistoryManager history = History.openFileHistory( runRef.historyFolder );
\r
120 ChartSettings cs = new ChartSettings();
\r
121 cs.history = history;
\r
122 cs.modelRef = modelRef;
\r
123 cs.experimentRef = experimentRef;
\r
124 cs.runRef = runRef;
\r
125 cs.chartRes = chartRes;
\r
133 for ( final ChartSettings cs : charts ) {
\r
134 UUID id = UUID.randomUUID();
\r
135 final TrendSpec trendSpec = ctx.session.syncRequest( new TrendSpecQuery( id, cs.chartRes ) );
\r
136 if ( cs.modelRef.enabledRunCount() > 1 ) {
\r
137 // Add run ref to the label
\r
138 trendSpec.name += " / " + cs.runRef.label;
\r
142 final MilestoneSpec milestones = ctx.session.syncRequest( new MilestoneSpecQuery( cs.experimentRef.resource ) );
\r
143 //final CanvasContext cctx = new CanvasContext( workerThread );
\r
144 final ExportException[] error = new ExportException[1];
\r
146 ThreadUtils.syncExec(workerThread, new Runnable() {
\r
148 public void run() {
\r
149 CanvasContext cctx = TrendInitializer.createDefaultCanvas(workerThread, cs.history, null, null, trendSpec);
\r
150 Page pdfPage = null;
\r
152 TrendNode trend = TrendInitializer.getTrendNode( cctx );
\r
153 trend.printing = true;
\r
155 String s = ExporterUtils.getUnionValue(ra, P_ITEMPLACEMENT);
\r
156 if ( s!=null ) trend.itemPlacement = ItemPlacement.valueOf(s);
\r
157 s = ExporterUtils.getUnionValue(ra, P_TIMEFORMAT);
\r
158 if ( s!=null ) trend.timeFormat = TimeFormat.valueOf(s);
\r
159 s = ExporterUtils.getUnionValue(ra, P_VALUEFORMAT);
\r
160 if ( s!=null ) trend.valueFormat = ValueFormat.valueOf(s);
\r
162 if (milestones!=null) trend.setMilestones(milestones);
\r
164 pdfPage = writer.createPage( null );
\r
165 Graphics2D g2d = pdfPage.createGraphics( true );
\r
167 Rectangle2D clip = new Rectangle2D.Double(0, 0, pdfPage.getWidth(), pdfPage.getHeight());
\r
168 g2d.setClip( clip );
\r
169 g2d.scale(0.25, 0.25);
\r
170 trend.autoscale(true, true);
\r
173 trend.render( g2d );
\r
177 cs.history.close();
\r
179 } catch (ExportException e) {
\r
183 if ( pdfPage != null )
\r
186 } catch (ExportException e) {
\r
187 if ( error[0]==null ) error[0] = e;
\r
192 if ( error[0] != null ) throw error[0];
\r
195 } catch (DatabaseException e) {
\r
196 throw new ExportException( e );
\r
197 } catch (AccessorConstructionException e) {
\r
198 throw new ExportException( e );
\r
200 workerThread.stopDispatchingEvents(true);
\r
207 public RecordType options(ExportContext context, Collection<String> content) throws ExportException {
\r
208 RecordType options = super.options(context, content);
\r
209 options.addComponent(S_CHART, chartOptions);
\r
214 public void fillDefaultPrefs(ExportContext ctx, Variant options) throws ExportException {
\r
215 super.fillDefaultPrefs(ctx, options);
\r
216 // Read from eclipse preferences
\r
218 RecordAccessor ra = Accessors.getAccessor(options);
\r
219 Preferences instPrefs = InstanceScope.INSTANCE.getNode( ChartPreferences.P_NODE );
\r
220 Preferences defaultPrefs = DefaultScope.INSTANCE.getNode( ChartPreferences.P_NODE );
\r
223 s = ExporterUtils.getPrefString(instPrefs, defaultPrefs, ChartPreferences.P_ITEMPLACEMENT);
\r
224 ExporterUtils.setUnionValue(ra, P_ITEMPLACEMENT, s);
\r
226 s = ExporterUtils.getPrefString(instPrefs, defaultPrefs, ChartPreferences.P_TIMEFORMAT);
\r
227 ExporterUtils.setUnionValue(ra, P_TIMEFORMAT, s);
\r
229 s = ExporterUtils.getPrefString(instPrefs, defaultPrefs, ChartPreferences.P_VALUEFORMAT);
\r
230 ExporterUtils.setUnionValue(ra, P_VALUEFORMAT, s);
\r
232 } catch (AccessorConstructionException e) {
\r
233 throw new ExportException(e);
\r
238 public void savePref(Variant options, Preferences contentScopeNode, Preferences workbenchScopeNode) throws ExportException {
\r
239 super.savePref(options, contentScopeNode, workbenchScopeNode);
\r
241 RecordAccessor ra = Accessors.getAccessor(options);
\r
244 s = ExporterUtils.getUnionValue(ra, P_ITEMPLACEMENT);
\r
245 ExporterUtils.setPrefString(contentScopeNode, ChartPreferences.P_ITEMPLACEMENT, s);
\r
246 ExporterUtils.setPrefString(workbenchScopeNode, ChartPreferences.P_ITEMPLACEMENT, s);
\r
248 s = ExporterUtils.getUnionValue(ra, P_TIMEFORMAT);
\r
249 ExporterUtils.setPrefString(contentScopeNode, ChartPreferences.P_TIMEFORMAT, s);
\r
250 ExporterUtils.setPrefString(workbenchScopeNode, ChartPreferences.P_TIMEFORMAT, s);
\r
252 s = ExporterUtils.getUnionValue(ra, P_VALUEFORMAT);
\r
253 ExporterUtils.setPrefString(contentScopeNode, ChartPreferences.P_VALUEFORMAT, s);
\r
254 ExporterUtils.setPrefString(workbenchScopeNode, ChartPreferences.P_VALUEFORMAT, s);
\r
256 } catch (AccessorConstructionException e) {
\r
257 throw new ExportException(e);
\r
263 public void loadPref(Variant options, Preferences contentScopeNode, Preferences workbenchScopeNode) throws ExportException {
\r
264 super.loadPref(options, contentScopeNode, workbenchScopeNode);
\r
266 RecordAccessor ra = Accessors.getAccessor(options);
\r
269 s = ExporterUtils.getPrefString(contentScopeNode, ChartPreferences.P_ITEMPLACEMENT);
\r
270 if ( s==null ) s = ExporterUtils.getPrefString(workbenchScopeNode, ChartPreferences.P_ITEMPLACEMENT);
\r
271 ExporterUtils.setUnionValue(ra, P_ITEMPLACEMENT, s);
\r
273 s = ExporterUtils.getPrefString(contentScopeNode, ChartPreferences.P_TIMEFORMAT);
\r
274 if ( s==null ) s = ExporterUtils.getPrefString(workbenchScopeNode, ChartPreferences.P_TIMEFORMAT);
\r
275 ExporterUtils.setUnionValue(ra, P_TIMEFORMAT, s);
\r
277 s = ExporterUtils.getPrefString(contentScopeNode, ChartPreferences.P_VALUEFORMAT);
\r
278 if ( s==null ) s = ExporterUtils.getPrefString(workbenchScopeNode, ChartPreferences.P_VALUEFORMAT);
\r
279 ExporterUtils.setUnionValue(ra, P_VALUEFORMAT, s);
\r
281 } catch (AccessorConstructionException e) {
\r
282 throw new ExportException(e);
\r
287 public List<String> validate(String contentUri, ExportContext context, Variant options) {
\r
288 return Collections.emptyList();
\r
291 static class ChartSettings {
\r
295 ExperimentRef experimentRef;
\r
297 HistoryManager history;
\r