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