]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFExportPage.java
Sync git svn branch with SVN repository r33219.
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / pdf / PDFExportPage.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.File;\r
15 import java.lang.reflect.InvocationTargetException;\r
16 import java.util.ArrayDeque;\r
17 import java.util.ArrayList;\r
18 import java.util.Collection;\r
19 import java.util.Deque;\r
20 import java.util.HashSet;\r
21 import java.util.List;\r
22 import java.util.Set;\r
23 import java.util.regex.Matcher;\r
24 import java.util.regex.Pattern;\r
25 \r
26 import org.eclipse.core.runtime.IPath;\r
27 import org.eclipse.core.runtime.IProgressMonitor;\r
28 import org.eclipse.core.runtime.Path;\r
29 import org.eclipse.core.runtime.SubMonitor;\r
30 import org.eclipse.jface.layout.GridDataFactory;\r
31 import org.eclipse.jface.operation.IRunnableWithProgress;\r
32 import org.eclipse.jface.resource.JFaceResources;\r
33 import org.eclipse.jface.resource.LocalResourceManager;\r
34 import org.eclipse.jface.viewers.CellLabelProvider;\r
35 import org.eclipse.jface.viewers.CheckStateChangedEvent;\r
36 import org.eclipse.jface.viewers.CheckboxTreeViewer;\r
37 import org.eclipse.jface.viewers.ICheckStateListener;\r
38 import org.eclipse.jface.viewers.ICheckStateProvider;\r
39 import org.eclipse.jface.viewers.ITreeContentProvider;\r
40 import org.eclipse.jface.viewers.StructuredSelection;\r
41 import org.eclipse.jface.viewers.TreeViewer;\r
42 import org.eclipse.jface.viewers.Viewer;\r
43 import org.eclipse.jface.viewers.ViewerCell;\r
44 import org.eclipse.jface.viewers.ViewerComparator;\r
45 import org.eclipse.jface.viewers.ViewerFilter;\r
46 import org.eclipse.jface.wizard.WizardPage;\r
47 import org.eclipse.swt.SWT;\r
48 import org.eclipse.swt.custom.CCombo;\r
49 import org.eclipse.swt.events.DisposeEvent;\r
50 import org.eclipse.swt.events.DisposeListener;\r
51 import org.eclipse.swt.events.ModifyEvent;\r
52 import org.eclipse.swt.events.ModifyListener;\r
53 import org.eclipse.swt.events.SelectionAdapter;\r
54 import org.eclipse.swt.events.SelectionEvent;\r
55 import org.eclipse.swt.events.SelectionListener;\r
56 import org.eclipse.swt.graphics.Color;\r
57 import org.eclipse.swt.layout.GridData;\r
58 import org.eclipse.swt.layout.GridLayout;\r
59 import org.eclipse.swt.layout.RowLayout;\r
60 import org.eclipse.swt.widgets.Button;\r
61 import org.eclipse.swt.widgets.Combo;\r
62 import org.eclipse.swt.widgets.Composite;\r
63 import org.eclipse.swt.widgets.Display;\r
64 import org.eclipse.swt.widgets.FileDialog;\r
65 import org.eclipse.swt.widgets.Label;\r
66 import org.eclipse.swt.widgets.Text;\r
67 import org.eclipse.swt.widgets.TreeItem;\r
68 import org.simantics.browsing.ui.common.views.DefaultFilterStrategy;\r
69 import org.simantics.browsing.ui.common.views.IFilterStrategy;\r
70 import org.simantics.databoard.Bindings;\r
71 import org.simantics.db.ReadGraph;\r
72 import org.simantics.db.Resource;\r
73 import org.simantics.db.common.NamedResource;\r
74 import org.simantics.db.common.request.ReadRequest;\r
75 import org.simantics.db.exception.DatabaseException;\r
76 import org.simantics.modeling.requests.Node;\r
77 import org.simantics.utils.FileUtils;\r
78 import org.simantics.utils.strings.AlphanumComparator;\r
79 import org.simantics.utils.ui.ISelectionUtils;\r
80 \r
81 public class PDFExportPage extends WizardPage {\r
82 \r
83         protected Display              display;\r
84 \r
85     protected PDFExportPlan       exportModel;\r
86 \r
87     protected IFilterStrategy      filterStrategy     = new DefaultFilterStrategy();\r
88 \r
89     protected Combo                modelSelector;\r
90     protected SelectionListener    modelSelectorListener;\r
91 \r
92     protected Text                 filter;\r
93 \r
94     protected Matcher              matcher            = null;\r
95 \r
96     protected CheckboxTreeViewer   tree;\r
97 \r
98     protected CCombo               exportLocation;\r
99     protected ModifyListener       exportLocationListener;\r
100 \r
101     protected Set<Node>            selectedNodes;\r
102 \r
103     protected LocalResourceManager resourceManager;\r
104     protected Color                noDiagramColor;\r
105     \r
106     protected Label                                toFileLabel;\r
107 \r
108     protected boolean              exportLocationTouchedByUser = false;\r
109 \r
110     ICheckStateProvider checkStateProvider = new ICheckStateProvider() {\r
111         @Override\r
112         public boolean isChecked(Object element) {\r
113             Node node = (Node) element;\r
114 \r
115             // Primarily checked if any children are selected.\r
116             Collection<Node> children = node.getChildren();\r
117             if (!children.isEmpty()) {\r
118                 for (Node child : node.getChildren())\r
119                     if (isChecked(child))\r
120                         return true;\r
121 \r
122                 // No children are checked, not checked.\r
123                 return false;\r
124             }\r
125 \r
126             // Otherwise checked only if selected.\r
127             return selectedNodes.contains(node);\r
128         }\r
129         @Override\r
130         public boolean isGrayed(Object element) {\r
131             Node node = (Node) element;\r
132 \r
133             // Grayed if there are children but not all of them are selected.\r
134             Collection<Node> children = node.getChildren();\r
135             if (!children.isEmpty()) {\r
136                 for (Node child : children)\r
137                     if (!selectedNodes.contains(child))\r
138                         return true;\r
139             }\r
140 \r
141             // Grayed if the node itself contains no diagram.\r
142             if (node.getDiagramResource() == null)\r
143                 return true;\r
144 \r
145             // Otherwise never grayed.\r
146             return false;\r
147         }\r
148     };\r
149 \r
150     protected PDFExportPage(PDFExportPlan model) {\r
151         super("Export Diagrams to PDF", "Define Exported Items", null);\r
152         this.exportModel = model;\r
153         this.selectedNodes = exportModel.selectedNodeSet;\r
154     }\r
155 \r
156     @Override\r
157     public void createControl(Composite parent) {\r
158         this.display = parent.getDisplay();\r
159 \r
160         Composite container = new Composite(parent, SWT.NONE);\r
161         {\r
162             GridLayout layout = new GridLayout();\r
163             layout.horizontalSpacing = 20;\r
164             layout.verticalSpacing = 10;\r
165             layout.numColumns = 3;\r
166             container.setLayout(layout);\r
167         }\r
168         resourceManager = new LocalResourceManager(JFaceResources.getResources());\r
169         container.addDisposeListener(new DisposeListener() {\r
170             @Override\r
171             public void widgetDisposed(DisposeEvent e) {\r
172                 resourceManager.dispose();\r
173             }\r
174         });\r
175         noDiagramColor = container.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY);\r
176 \r
177         Label modelSelectorLabel = new Label(container, SWT.NONE);\r
178         modelSelectorLabel.setText("Model Selector:");\r
179         GridDataFactory.fillDefaults().span(1, 1).applyTo(modelSelectorLabel);\r
180         modelSelector = new Combo(container, SWT.BORDER | SWT.READ_ONLY);\r
181         GridDataFactory.fillDefaults().span(2, 1).applyTo(modelSelector);\r
182         modelSelectorListener = new SelectionAdapter() {\r
183             @Override\r
184             public void widgetSelected(SelectionEvent e) {\r
185                 NamedResource data = (NamedResource) modelSelector.getData(String.valueOf(modelSelector.getSelectionIndex()));\r
186                 scheduleInitializeData(data);\r
187             }\r
188         };\r
189 \r
190         // Fill model selector combo\r
191         for (int i = 0; i < exportModel.selectableModels.size(); ++i) {\r
192             NamedResource nr = exportModel.selectableModels.get(i);\r
193             modelSelector.add(nr.getName());\r
194             modelSelector.setData("" + i, nr);\r
195         }\r
196 \r
197         modelSelector.addSelectionListener(modelSelectorListener);\r
198 \r
199 //        Label label = new Label(container, SWT.NONE);\r
200 //        label.setText("Diagrams to Export:");\r
201 //        GridDataFactory.fillDefaults().span(3, 1).applyTo(label);\r
202 \r
203         Label filterLabel = new Label(container, SWT.NONE);\r
204         filterLabel.setText("Fi&lter:");\r
205         GridDataFactory.fillDefaults().span(1, 1).applyTo(filterLabel);\r
206         filter = new Text(container, SWT.BORDER);\r
207         GridDataFactory.fillDefaults().span(2, 1).applyTo(filter);\r
208         filter.addModifyListener(new ModifyListener() {\r
209             @Override\r
210             public void modifyText(ModifyEvent e) {\r
211                 resetFilterString(filter.getText());\r
212             }\r
213         });\r
214 \r
215         tree = new CheckboxTreeViewer(container, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);\r
216         {\r
217             tree.setUseHashlookup(true);\r
218             GridDataFactory.fillDefaults().grab(true, true).span(3, 1).applyTo(tree.getControl());\r
219             tree.getControl().setToolTipText("Selects the diagram to include in the exported document.");\r
220             tree.setAutoExpandLevel(TreeViewer.ALL_LEVELS);\r
221             tree.addCheckStateListener(new ICheckStateListener(){\r
222                 void addOrRemoveSelection(Node node, boolean add) {\r
223                     if (add)\r
224                         selectedNodes.add(node);\r
225                     else\r
226                         selectedNodes.remove(node);\r
227                 }\r
228                 void addOrRemoveSelectionRec(Node node, boolean add) {\r
229                     addOrRemoveSelection(node, add);\r
230                     for (Node child : node.getChildren())\r
231                         addOrRemoveSelectionRec(child, add);\r
232                 }\r
233                 @Override\r
234                 public void checkStateChanged(CheckStateChangedEvent event) {\r
235                     final boolean checked = event.getChecked();\r
236                     Node checkedNode = (Node) event.getElement();\r
237 \r
238                     Set<Node> nodes = new HashSet<Node>();\r
239                     Set<Node> selection = ISelectionUtils.filterSetSelection(tree.getSelection(), Node.class);\r
240                     if (selection.contains(checkedNode))\r
241                         nodes.addAll(selection);\r
242                     else\r
243                         tree.setSelection(StructuredSelection.EMPTY);\r
244                     nodes.add(checkedNode);\r
245 \r
246                     for (Node node : nodes) {\r
247                         addOrRemoveSelectionRec(node, checked);\r
248 \r
249 //                        tree.setSubtreeChecked(node, checked);\r
250 //                         The checked node is always either checked or not checked, never grayed.\r
251 //                        tree.setGrayed(node, checkStateProvider.isGrayed(node));\r
252 \r
253 //                        Node parent = node.getParent();\r
254 //                        if (parent != null) {\r
255 //                            tree.setChecked(parent, checkStateProvider.isChecked(parent));\r
256 //                            tree.setGrayed(parent, checkStateProvider.isGrayed(parent));\r
257 //                        }\r
258                     }\r
259 \r
260                     refreshAndExpandTree();\r
261                     validatePage();\r
262                 }\r
263             });\r
264 \r
265             tree.setContentProvider(new ITreeContentProvider(){\r
266                 @Override\r
267                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
268                 }\r
269                 @Override\r
270                 public void dispose() {\r
271                 }\r
272                 @Override\r
273                 public Object[] getElements(Object inputElement) {\r
274                     return exportModel.nodes.roots.toArray();\r
275                 }\r
276                 @Override\r
277                 public boolean hasChildren(Object element) {\r
278                     Node n = (Node) element;\r
279                     if (n.getChildren().isEmpty()) return false;\r
280                         for (Node c : n.getChildren()) if (hasDiagram(c)) return true; \r
281                     return false;\r
282                     \r
283                 }\r
284                 @Override\r
285                 public Object getParent(Object element) {\r
286                     Node n = (Node) element;\r
287                     return n.getParent();\r
288                 }\r
289                 @Override\r
290                 public Object[] getChildren(Object parentElement) {\r
291                     Node n = (Node) parentElement;\r
292                         List<Object> result = new ArrayList<Object>( n.getChildren().size() );\r
293                         for (Node c : n.getChildren()) \r
294                                 if (hasDiagram(c)) \r
295                                         result.add(c);\r
296                     return result.toArray();\r
297                 }\r
298                 \r
299                 boolean hasDiagram(Node n)\r
300                 {                       \r
301                         if (n.getDiagramResource()!=null) return true;\r
302                         for (Node c : n.getChildren()) if (hasDiagram(c)) return true;\r
303                         return false;\r
304                 }\r
305             });\r
306             tree.setLabelProvider(new CellLabelProvider() {\r
307                 @Override\r
308                 public void update(ViewerCell cell) {\r
309                     Object e = cell.getElement();\r
310                     if (e instanceof Node) {\r
311                         Node n = (Node) e;\r
312                         String name = DiagramPrinter.formDiagramName(n, false);\r
313                         cell.setText(name);\r
314 \r
315                         if (n.getDiagramResource() == null)\r
316                             cell.setForeground(noDiagramColor);\r
317                         else\r
318                             cell.setForeground(null);\r
319                     } else {\r
320                         cell.setText("invalid input: " + e.getClass().getSimpleName());\r
321                     }\r
322                 }\r
323             });\r
324             tree.setComparator(new ViewerComparator(AlphanumComparator.CASE_INSENSITIVE_COMPARATOR));\r
325             tree.setFilters(new ViewerFilter[] {\r
326                     new ViewerFilter() {\r
327                         @Override\r
328                         public boolean select(Viewer viewer, Object parentElement, Object element) {\r
329                             if (matcher == null)\r
330                                 return true;\r
331 \r
332                             Node node = (Node) element;\r
333                             // If any children are in sight, show this element.\r
334                             for (Node child : node.getChildren()) {\r
335                                 if (select(viewer, element, child))\r
336                                     return true;\r
337                             }\r
338 \r
339                             return matcher.reset(node.getName().toLowerCase()).matches();\r
340                         }\r
341                     }\r
342             });\r
343             tree.setCheckStateProvider(checkStateProvider);\r
344         }\r
345 \r
346         Composite bar = new Composite(container, SWT.NONE);\r
347         GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo(bar);\r
348         bar.setLayout(new RowLayout());\r
349         Button selectAll = new Button(bar, SWT.PUSH);\r
350         selectAll.setText("Select &All");\r
351         selectAll.addSelectionListener(new SelectionAdapter() {\r
352             @Override\r
353             public void widgetSelected(SelectionEvent e) {\r
354                 selectedNodes.addAll(exportModel.nodes.breadthFirstFlatten());\r
355                 for (Node root : exportModel.nodes.roots)\r
356                     tree.setSubtreeChecked(root, true);\r
357                 validatePage();\r
358             }\r
359         });\r
360         Button clearSelection = new Button(bar, SWT.PUSH);\r
361         clearSelection.setText("&Clear Selection");\r
362         clearSelection.addSelectionListener(new SelectionAdapter() {\r
363             @Override\r
364             public void widgetSelected(SelectionEvent e) {\r
365                 selectedNodes.clear();\r
366                 for (Node root : exportModel.nodes.roots)\r
367                     tree.setSubtreeChecked(root, false);\r
368                 validatePage();\r
369             }\r
370         });\r
371         Button selectVisible = new Button(bar, SWT.PUSH);\r
372         selectVisible.setText("&Select Visible");\r
373         selectVisible.addSelectionListener(new SelectionAdapter() {\r
374             @Override\r
375             public void widgetSelected(SelectionEvent e) {\r
376                 selectedNodes.addAll(getVisibleNodes());\r
377                 refreshAndExpandTree();\r
378                 validatePage();\r
379             }\r
380         });\r
381         Button deselectVisible = new Button(bar, SWT.PUSH);\r
382         deselectVisible.setText("&Deselect Visible");\r
383         deselectVisible.addSelectionListener(new SelectionAdapter() {\r
384             @Override\r
385             public void widgetSelected(SelectionEvent e) {\r
386                 selectedNodes.removeAll(getVisibleNodes());\r
387                 refreshAndExpandTree();\r
388                 validatePage();\r
389             }\r
390         });\r
391 \r
392         toFileLabel = new Label(container, SWT.NONE);\r
393         toFileLabel.setText("&To file:");\r
394         exportLocation = new CCombo(container, SWT.BORDER);\r
395         {\r
396             exportLocation.setText("");\r
397             GridDataFactory.fillDefaults().grab(true, false).span(1, 1).applyTo(exportLocation);\r
398 \r
399             for (String path : exportModel.recentLocations) {\r
400                 exportLocation.add(path);\r
401             }\r
402 \r
403             exportLocationListener = new ModifyListener() {\r
404                 @Override\r
405                 public void modifyText(ModifyEvent e) {\r
406                     //System.out.println("export location changed by user");\r
407                     exportLocationTouchedByUser = true;\r
408                     validatePage();\r
409                 }\r
410             };\r
411             exportLocation.addModifyListener(exportLocationListener);\r
412         }\r
413         Button browseFileButton = new Button(container, SWT.PUSH);\r
414         {\r
415             browseFileButton.setText("Browse...");\r
416             browseFileButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
417             browseFileButton.addSelectionListener(new SelectionAdapter() {\r
418                 @Override\r
419                 public void widgetSelected(SelectionEvent e) {\r
420                     FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);\r
421                     dialog.setFilterExtensions(new String[] { "*.pdf" });\r
422                     dialog.setFilterNames(new String[] { "PDF Document" });\r
423                     String loc = exportLocation.getText();\r
424                     if (loc != null) {\r
425                         IPath p = new Path(loc);\r
426                         File f = p.toFile();\r
427                         if (f.isDirectory()) {\r
428                             dialog.setFilterPath(f.toString());\r
429                         } else if (f.isFile()) {\r
430                             IPath path = p.removeLastSegments(1);\r
431                             String name = p.lastSegment();\r
432                             dialog.setFilterPath(path.toOSString());\r
433                             dialog.setFileName(name);\r
434                         } else {\r
435                             dialog.setFilterPath(f.toString());\r
436                             IPath path = p.removeLastSegments(1);\r
437                             String name = p.lastSegment();\r
438                             f = path.toFile();\r
439                             if (f.isDirectory()) {\r
440                                 dialog.setFilterPath(path.toOSString());\r
441                             }\r
442                             dialog.setFileName(name);\r
443                         }\r
444                     }\r
445                     String file = dialog.open();\r
446                     if (file == null)\r
447                         return;\r
448                     exportLocation.setText(file);\r
449                     validatePage();\r
450                 }\r
451             });\r
452         }\r
453 \r
454         final Button zoomToFitButton = new Button(container, SWT.CHECK);\r
455         GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo(zoomToFitButton);\r
456         zoomToFitButton.setText("F&it by content");\r
457         zoomToFitButton.setSelection(exportModel.fitContentToPageMargins);\r
458         zoomToFitButton.addSelectionListener(new SelectionAdapter() {\r
459             @Override\r
460             public void widgetSelected(SelectionEvent e) {\r
461                 exportModel.fitContentToPageMargins = zoomToFitButton.getSelection();\r
462             }\r
463         });\r
464 \r
465         /*\r
466         final Button attachTGButton = new Button(container, SWT.CHECK);\r
467         GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo( attachTGButton );\r
468         attachTGButton.setText("Attach &TG (Importable diagram)");\r
469         attachTGButton.setSelection(exportModel.attachTG);\r
470         attachTGButton.addSelectionListener(new SelectionAdapter() {\r
471             @Override\r
472             public void widgetSelected(SelectionEvent e) {\r
473                 exportModel.attachTG = attachTGButton.getSelection();\r
474             }\r
475         });\r
476         */\r
477         \r
478         final Button attachWikiButton = new Button(container, SWT.CHECK);\r
479         GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo( attachWikiButton );\r
480         attachWikiButton.setText("Attach &Wiki page");\r
481         attachWikiButton.setSelection(exportModel.attachWiki);\r
482         attachWikiButton.addSelectionListener(new SelectionAdapter() {\r
483             @Override\r
484             public void widgetSelected(SelectionEvent e) {\r
485                 exportModel.attachWiki = attachWikiButton.getSelection();\r
486             }\r
487         });\r
488         \r
489         setControl(container);\r
490         validatePage();\r
491 \r
492         scheduleInitializeData(exportModel.selection);\r
493     }\r
494 \r
495     private void scheduleInitializeData(final NamedResource modelSelection) {\r
496         display.asyncExec(new Runnable() {\r
497             @Override\r
498             public void run() {\r
499                 if (filter.isDisposed())\r
500                     return;\r
501 \r
502                 try {\r
503                     initializeData(modelSelection);\r
504                 } catch (DatabaseException e) {\r
505                     e.printStackTrace();\r
506                 } catch (InvocationTargetException e) {\r
507                     e.getTargetException().printStackTrace();\r
508                 } catch (InterruptedException e) {\r
509                     e.printStackTrace();\r
510                 }\r
511             }\r
512         });\r
513     }\r
514 \r
515     private NamedResource getSelectedModel() {\r
516         int sel = modelSelector.getSelectionIndex();\r
517         if (sel != -1) {\r
518             NamedResource nr = (NamedResource) modelSelector.getData("" + sel);\r
519             return nr;\r
520         }\r
521         return null;\r
522     }\r
523 \r
524     private void setExportLocationWithoutNotification(String text) {\r
525         exportLocation.removeModifyListener(exportLocationListener);\r
526         exportLocation.setText(text);\r
527         exportLocation.addModifyListener(exportLocationListener);\r
528     }\r
529 \r
530     private Collection<Node> getVisibleNodes() {\r
531         Collection<Node> result = new ArrayList<Node>();\r
532 \r
533         Deque<TreeItem> todo = new ArrayDeque<TreeItem>();\r
534         for (TreeItem ti : tree.getTree().getItems()) {\r
535             todo.add(ti);\r
536         }\r
537 \r
538         while (!todo.isEmpty()) {\r
539             TreeItem item = todo.removeLast();\r
540             Node node = (Node) item.getData();\r
541             result.add(node);\r
542 \r
543             for (TreeItem child : item.getItems()) {\r
544                 todo.add(child);\r
545             }\r
546         }\r
547 \r
548         return result;\r
549     }\r
550 \r
551     private void resetFilterString(String filterString) {\r
552         String patternString = filterStrategy.toPatternString(filterString);\r
553         if (patternString == null) {\r
554             matcher = null;\r
555         } else {\r
556             matcher = Pattern.compile(patternString).matcher("");\r
557         }\r
558         refreshAndExpandTree();\r
559     }\r
560 \r
561     private void refreshAndExpandTree() {\r
562         tree.refresh();\r
563         tree.expandAll();\r
564     }\r
565 \r
566     private void initializeData(final NamedResource modelSelection) throws DatabaseException, InvocationTargetException, InterruptedException {\r
567         if (modelSelection != null) {\r
568             // Process input selection to find the model/state selected by default.\r
569 \r
570             // This may take longer than the user wants to wait without\r
571             // notification.\r
572 \r
573             // !PROFILE\r
574             long time = System.nanoTime();\r
575 \r
576             getWizard().getContainer().run(true, true, new IRunnableWithProgress() {\r
577                 @Override\r
578                 public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {\r
579                     try {\r
580                         final SubMonitor mon = SubMonitor.convert(monitor, "Searching for exportable diagrams...", 100);\r
581                         exportModel.sessionContext.getSession().syncRequest(new ReadRequest() {\r
582                             @Override\r
583                             public void run(ReadGraph graph) throws DatabaseException {\r
584                                 exportModel.nodes = DiagramPrinter.browse(mon.newChild(100), graph, new Resource[] { modelSelection.getResource() });\r
585                             }\r
586                         });\r
587                     } catch (DatabaseException e) {\r
588                         throw new InvocationTargetException(e);\r
589                     } finally {\r
590                         monitor.done();\r
591                     }\r
592                 }\r
593             });\r
594 \r
595             // !PROFILE\r
596             long endTime = System.nanoTime();\r
597             if (exportModel.nodes != null)\r
598                 System.out.println("Found " + exportModel.nodes.diagrams.size() + " diagrams in " + ((endTime - time)*1e-9) + " seconds.");\r
599         }\r
600 \r
601         // Browsing was canceled by user.\r
602         if (exportModel.nodes == null)\r
603             return;\r
604 \r
605         // Setup selected states, select everything by default.\r
606         selectedNodes.clear();\r
607         selectedNodes.addAll(exportModel.nodes.breadthFirstFlatten());\r
608 \r
609         tree.setInput(this);\r
610 \r
611         for (Node root : exportModel.nodes.roots) {\r
612             tree.setSubtreeChecked(root, true);\r
613         }\r
614 \r
615         resetFilterString(filter.getText());\r
616 \r
617         modelSelector.removeSelectionListener(modelSelectorListener);\r
618         int selectedIndex = -1;\r
619         for (int i = 0; i < modelSelector.getItemCount(); ++i) {\r
620             Object obj = modelSelector.getData("" + i);\r
621             if (org.simantics.utils.ObjectUtils.objectEquals(obj, modelSelection)) {\r
622                 selectedIndex = i;\r
623             }\r
624         }\r
625         if (selectedIndex == -1 && modelSelector.getItemCount() > 0)\r
626             selectedIndex = 0;\r
627         if (selectedIndex != -1)\r
628             modelSelector.select(selectedIndex);\r
629         modelSelector.addSelectionListener(modelSelectorListener);\r
630 \r
631         validatePage();\r
632     }\r
633 \r
634     void validatePage() {\r
635         //System.out.println("VALIDATE PAGE: " + exportLocationTouchedByUser);\r
636         if (selectedNodes.size() == 0) {\r
637             setMessage("Select the diagrams to export.");\r
638             setErrorMessage(null);\r
639             setPageComplete(false);\r
640             return;\r
641         }\r
642 \r
643         if (!exportLocationTouchedByUser) {\r
644             String generatedName = null;\r
645             // Generate file name automatically if user hasn't touched the name manually.\r
646             NamedResource nr = getSelectedModel();\r
647             if (nr != null) {\r
648                 if (selectedNodes.size() == 1) {\r
649                     generatedName = nr.getName() + "-" + selectedNodes.iterator().next().getName();\r
650                 } else {\r
651                     generatedName = nr.getName();\r
652                 }\r
653             }\r
654             //System.out.println("generate name: " + generatedName);\r
655             if (generatedName != null) {\r
656                 if (!FileUtils.isValidFileName(generatedName))\r
657                     generatedName = (String) Bindings.STR_VARIANT.createUnchecked(Bindings.STRING, generatedName);\r
658                 String name = generatedName + ".pdf";\r
659                 \r
660                 abu:\r
661                 if ( !exportModel.recentLocations.isEmpty() ) {\r
662                         \r
663                         for ( String loc : exportModel.recentLocations )\r
664                         {\r
665                                 if ( loc.endsWith(name) && !loc.equals(name) ) {\r
666                                         name = loc;\r
667                                         break abu; \r
668                                 }\r
669                         }\r
670                         \r
671                         String firstLine = exportModel.recentLocations.iterator().next();\r
672                         File f = new File(firstLine);    \r
673                         File parentFile = f.getParentFile();\r
674                         if ( parentFile!=null ) {\r
675                                 name = new File( f.getParentFile(), name ).getAbsolutePath();\r
676                         }\r
677                 }\r
678                 setExportLocationWithoutNotification(name);\r
679             }\r
680         }\r
681 \r
682         String exportLoc = exportLocation.getText();\r
683         if (exportLoc.isEmpty()) {\r
684             setMessage("Select an export target file.");\r
685             setErrorMessage(null);\r
686             setPageComplete(false);\r
687             return;\r
688         }\r
689         File file = new File(exportLoc);\r
690         if (file.exists()) {\r
691             if (file.isDirectory()) {\r
692                 setErrorMessage("The target already exists and it is a directory.");\r
693                 setPageComplete(false);\r
694                 return;\r
695             }\r
696             if (!file.isFile()) {\r
697                 setErrorMessage("The target already exists and it is a not a regular file.");\r
698                 setPageComplete(false);\r
699                 return;\r
700             }\r
701         }\r
702         exportModel.exportLocation = file;\r
703 \r
704         int diagramCount = 0;\r
705         for (Node n : selectedNodes)\r
706             if (n.getDiagramResource() != null)\r
707                 ++diagramCount;\r
708 \r
709         String msg = diagramCount + " diagrams selected for export.";\r
710 \r
711         setMessage(msg);\r
712         setErrorMessage(null);\r
713         setPageComplete(true);\r
714     }\r
715 \r
716 }\r