--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.modeling.ui.pdf;\r
+\r
+import java.io.File;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.util.ArrayDeque;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Deque;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.eclipse.core.runtime.IPath;\r
+import org.eclipse.core.runtime.IProgressMonitor;\r
+import org.eclipse.core.runtime.Path;\r
+import org.eclipse.core.runtime.SubMonitor;\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.operation.IRunnableWithProgress;\r
+import org.eclipse.jface.resource.JFaceResources;\r
+import org.eclipse.jface.resource.LocalResourceManager;\r
+import org.eclipse.jface.viewers.CellLabelProvider;\r
+import org.eclipse.jface.viewers.CheckStateChangedEvent;\r
+import org.eclipse.jface.viewers.CheckboxTreeViewer;\r
+import org.eclipse.jface.viewers.ICheckStateListener;\r
+import org.eclipse.jface.viewers.ICheckStateProvider;\r
+import org.eclipse.jface.viewers.ITreeContentProvider;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.jface.viewers.TreeViewer;\r
+import org.eclipse.jface.viewers.Viewer;\r
+import org.eclipse.jface.viewers.ViewerCell;\r
+import org.eclipse.jface.viewers.ViewerComparator;\r
+import org.eclipse.jface.viewers.ViewerFilter;\r
+import org.eclipse.jface.wizard.WizardPage;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.CCombo;\r
+import org.eclipse.swt.events.DisposeEvent;\r
+import org.eclipse.swt.events.DisposeListener;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.layout.RowLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Combo;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.FileDialog;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.eclipse.swt.widgets.TreeItem;\r
+import org.simantics.browsing.ui.common.views.DefaultFilterStrategy;\r
+import org.simantics.browsing.ui.common.views.IFilterStrategy;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.NamedResource;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.modeling.requests.Node;\r
+import org.simantics.utils.FileUtils;\r
+import org.simantics.utils.strings.AlphanumComparator;\r
+import org.simantics.utils.ui.ISelectionUtils;\r
+\r
+public class PDFExportPage extends WizardPage {\r
+\r
+ protected Display display;\r
+\r
+ protected PDFExportPlan exportModel;\r
+\r
+ protected IFilterStrategy filterStrategy = new DefaultFilterStrategy();\r
+\r
+ protected Combo modelSelector;\r
+ protected SelectionListener modelSelectorListener;\r
+\r
+ protected Text filter;\r
+\r
+ protected Matcher matcher = null;\r
+\r
+ protected CheckboxTreeViewer tree;\r
+\r
+ protected CCombo exportLocation;\r
+ protected ModifyListener exportLocationListener;\r
+\r
+ protected Set<Node> selectedNodes;\r
+\r
+ protected LocalResourceManager resourceManager;\r
+ protected Color noDiagramColor;\r
+ \r
+ protected Label toFileLabel;\r
+\r
+ protected boolean exportLocationTouchedByUser = false;\r
+\r
+ ICheckStateProvider checkStateProvider = new ICheckStateProvider() {\r
+ @Override\r
+ public boolean isChecked(Object element) {\r
+ Node node = (Node) element;\r
+\r
+ // Primarily checked if any children are selected.\r
+ Collection<Node> children = node.getChildren();\r
+ if (!children.isEmpty()) {\r
+ for (Node child : node.getChildren())\r
+ if (isChecked(child))\r
+ return true;\r
+\r
+ // No children are checked, not checked.\r
+ return false;\r
+ }\r
+\r
+ // Otherwise checked only if selected.\r
+ return selectedNodes.contains(node);\r
+ }\r
+ @Override\r
+ public boolean isGrayed(Object element) {\r
+ Node node = (Node) element;\r
+\r
+ // Grayed if there are children but not all of them are selected.\r
+ Collection<Node> children = node.getChildren();\r
+ if (!children.isEmpty()) {\r
+ for (Node child : children)\r
+ if (!selectedNodes.contains(child))\r
+ return true;\r
+ }\r
+\r
+ // Grayed if the node itself contains no diagram.\r
+ if (node.getDiagramResource() == null)\r
+ return true;\r
+\r
+ // Otherwise never grayed.\r
+ return false;\r
+ }\r
+ };\r
+\r
+ protected PDFExportPage(PDFExportPlan model) {\r
+ super("Export Diagrams to PDF", "Define Exported Items", null);\r
+ this.exportModel = model;\r
+ this.selectedNodes = exportModel.selectedNodeSet;\r
+ }\r
+\r
+ @Override\r
+ public void createControl(Composite parent) {\r
+ this.display = parent.getDisplay();\r
+\r
+ Composite container = new Composite(parent, SWT.NONE);\r
+ {\r
+ GridLayout layout = new GridLayout();\r
+ layout.horizontalSpacing = 20;\r
+ layout.verticalSpacing = 10;\r
+ layout.numColumns = 3;\r
+ container.setLayout(layout);\r
+ }\r
+ resourceManager = new LocalResourceManager(JFaceResources.getResources());\r
+ container.addDisposeListener(new DisposeListener() {\r
+ @Override\r
+ public void widgetDisposed(DisposeEvent e) {\r
+ resourceManager.dispose();\r
+ }\r
+ });\r
+ noDiagramColor = container.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY);\r
+\r
+ Label modelSelectorLabel = new Label(container, SWT.NONE);\r
+ modelSelectorLabel.setText("Model Selector:");\r
+ GridDataFactory.fillDefaults().span(1, 1).applyTo(modelSelectorLabel);\r
+ modelSelector = new Combo(container, SWT.BORDER | SWT.READ_ONLY);\r
+ GridDataFactory.fillDefaults().span(2, 1).applyTo(modelSelector);\r
+ modelSelectorListener = new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ NamedResource data = (NamedResource) modelSelector.getData(String.valueOf(modelSelector.getSelectionIndex()));\r
+ scheduleInitializeData(data);\r
+ }\r
+ };\r
+\r
+ // Fill model selector combo\r
+ for (int i = 0; i < exportModel.selectableModels.size(); ++i) {\r
+ NamedResource nr = exportModel.selectableModels.get(i);\r
+ modelSelector.add(nr.getName());\r
+ modelSelector.setData("" + i, nr);\r
+ }\r
+\r
+ modelSelector.addSelectionListener(modelSelectorListener);\r
+\r
+// Label label = new Label(container, SWT.NONE);\r
+// label.setText("Diagrams to Export:");\r
+// GridDataFactory.fillDefaults().span(3, 1).applyTo(label);\r
+\r
+ Label filterLabel = new Label(container, SWT.NONE);\r
+ filterLabel.setText("Fi<er:");\r
+ GridDataFactory.fillDefaults().span(1, 1).applyTo(filterLabel);\r
+ filter = new Text(container, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().span(2, 1).applyTo(filter);\r
+ filter.addModifyListener(new ModifyListener() {\r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ resetFilterString(filter.getText());\r
+ }\r
+ });\r
+\r
+ tree = new CheckboxTreeViewer(container, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);\r
+ {\r
+ tree.setUseHashlookup(true);\r
+ GridDataFactory.fillDefaults().grab(true, true).span(3, 1).applyTo(tree.getControl());\r
+ tree.getControl().setToolTipText("Selects the diagram to include in the exported document.");\r
+ tree.setAutoExpandLevel(TreeViewer.ALL_LEVELS);\r
+ tree.addCheckStateListener(new ICheckStateListener(){\r
+ void addOrRemoveSelection(Node node, boolean add) {\r
+ if (add)\r
+ selectedNodes.add(node);\r
+ else\r
+ selectedNodes.remove(node);\r
+ }\r
+ void addOrRemoveSelectionRec(Node node, boolean add) {\r
+ addOrRemoveSelection(node, add);\r
+ for (Node child : node.getChildren())\r
+ addOrRemoveSelectionRec(child, add);\r
+ }\r
+ @Override\r
+ public void checkStateChanged(CheckStateChangedEvent event) {\r
+ final boolean checked = event.getChecked();\r
+ Node checkedNode = (Node) event.getElement();\r
+\r
+ Set<Node> nodes = new HashSet<Node>();\r
+ Set<Node> selection = ISelectionUtils.filterSetSelection(tree.getSelection(), Node.class);\r
+ if (selection.contains(checkedNode))\r
+ nodes.addAll(selection);\r
+ else\r
+ tree.setSelection(StructuredSelection.EMPTY);\r
+ nodes.add(checkedNode);\r
+\r
+ for (Node node : nodes) {\r
+ addOrRemoveSelectionRec(node, checked);\r
+\r
+// tree.setSubtreeChecked(node, checked);\r
+// The checked node is always either checked or not checked, never grayed.\r
+// tree.setGrayed(node, checkStateProvider.isGrayed(node));\r
+\r
+// Node parent = node.getParent();\r
+// if (parent != null) {\r
+// tree.setChecked(parent, checkStateProvider.isChecked(parent));\r
+// tree.setGrayed(parent, checkStateProvider.isGrayed(parent));\r
+// }\r
+ }\r
+\r
+ refreshAndExpandTree();\r
+ validatePage();\r
+ }\r
+ });\r
+\r
+ tree.setContentProvider(new ITreeContentProvider(){\r
+ @Override\r
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
+ }\r
+ @Override\r
+ public void dispose() {\r
+ }\r
+ @Override\r
+ public Object[] getElements(Object inputElement) {\r
+ return exportModel.nodes.roots.toArray();\r
+ }\r
+ @Override\r
+ public boolean hasChildren(Object element) {\r
+ Node n = (Node) element;\r
+ if (n.getChildren().isEmpty()) return false;\r
+ for (Node c : n.getChildren()) if (hasDiagram(c)) return true; \r
+ return false;\r
+ \r
+ }\r
+ @Override\r
+ public Object getParent(Object element) {\r
+ Node n = (Node) element;\r
+ return n.getParent();\r
+ }\r
+ @Override\r
+ public Object[] getChildren(Object parentElement) {\r
+ Node n = (Node) parentElement;\r
+ List<Object> result = new ArrayList<Object>( n.getChildren().size() );\r
+ for (Node c : n.getChildren()) \r
+ if (hasDiagram(c)) \r
+ result.add(c);\r
+ return result.toArray();\r
+ }\r
+ \r
+ boolean hasDiagram(Node n)\r
+ { \r
+ if (n.getDiagramResource()!=null) return true;\r
+ for (Node c : n.getChildren()) if (hasDiagram(c)) return true;\r
+ return false;\r
+ }\r
+ });\r
+ tree.setLabelProvider(new CellLabelProvider() {\r
+ @Override\r
+ public void update(ViewerCell cell) {\r
+ Object e = cell.getElement();\r
+ if (e instanceof Node) {\r
+ Node n = (Node) e;\r
+ String name = DiagramPrinter.formDiagramName(n, false);\r
+ cell.setText(name);\r
+\r
+ if (n.getDiagramResource() == null)\r
+ cell.setForeground(noDiagramColor);\r
+ else\r
+ cell.setForeground(null);\r
+ } else {\r
+ cell.setText("invalid input: " + e.getClass().getSimpleName());\r
+ }\r
+ }\r
+ });\r
+ tree.setComparator(new ViewerComparator(AlphanumComparator.CASE_INSENSITIVE_COMPARATOR));\r
+ tree.setFilters(new ViewerFilter[] {\r
+ new ViewerFilter() {\r
+ @Override\r
+ public boolean select(Viewer viewer, Object parentElement, Object element) {\r
+ if (matcher == null)\r
+ return true;\r
+\r
+ Node node = (Node) element;\r
+ // If any children are in sight, show this element.\r
+ for (Node child : node.getChildren()) {\r
+ if (select(viewer, element, child))\r
+ return true;\r
+ }\r
+\r
+ return matcher.reset(node.getName().toLowerCase()).matches();\r
+ }\r
+ }\r
+ });\r
+ tree.setCheckStateProvider(checkStateProvider);\r
+ }\r
+\r
+ Composite bar = new Composite(container, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo(bar);\r
+ bar.setLayout(new RowLayout());\r
+ Button selectAll = new Button(bar, SWT.PUSH);\r
+ selectAll.setText("Select &All");\r
+ selectAll.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ selectedNodes.addAll(exportModel.nodes.breadthFirstFlatten());\r
+ for (Node root : exportModel.nodes.roots)\r
+ tree.setSubtreeChecked(root, true);\r
+ validatePage();\r
+ }\r
+ });\r
+ Button clearSelection = new Button(bar, SWT.PUSH);\r
+ clearSelection.setText("&Clear Selection");\r
+ clearSelection.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ selectedNodes.clear();\r
+ for (Node root : exportModel.nodes.roots)\r
+ tree.setSubtreeChecked(root, false);\r
+ validatePage();\r
+ }\r
+ });\r
+ Button selectVisible = new Button(bar, SWT.PUSH);\r
+ selectVisible.setText("&Select Visible");\r
+ selectVisible.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ selectedNodes.addAll(getVisibleNodes());\r
+ refreshAndExpandTree();\r
+ validatePage();\r
+ }\r
+ });\r
+ Button deselectVisible = new Button(bar, SWT.PUSH);\r
+ deselectVisible.setText("&Deselect Visible");\r
+ deselectVisible.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ selectedNodes.removeAll(getVisibleNodes());\r
+ refreshAndExpandTree();\r
+ validatePage();\r
+ }\r
+ });\r
+\r
+ toFileLabel = new Label(container, SWT.NONE);\r
+ toFileLabel.setText("&To file:");\r
+ exportLocation = new CCombo(container, SWT.BORDER);\r
+ {\r
+ exportLocation.setText("");\r
+ GridDataFactory.fillDefaults().grab(true, false).span(1, 1).applyTo(exportLocation);\r
+\r
+ for (String path : exportModel.recentLocations) {\r
+ exportLocation.add(path);\r
+ }\r
+\r
+ exportLocationListener = new ModifyListener() {\r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ System.out.println("export location changed by user");\r
+ exportLocationTouchedByUser = true;\r
+ validatePage();\r
+ }\r
+ };\r
+ exportLocation.addModifyListener(exportLocationListener);\r
+ }\r
+ Button browseFileButton = new Button(container, SWT.PUSH);\r
+ {\r
+ browseFileButton.setText("Browse...");\r
+ browseFileButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+ browseFileButton.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);\r
+ dialog.setFilterExtensions(new String[] { "*.pdf" });\r
+ dialog.setFilterNames(new String[] { "PDF Document" });\r
+ String loc = exportLocation.getText();\r
+ if (loc != null) {\r
+ IPath p = new Path(loc);\r
+ File f = p.toFile();\r
+ if (f.isDirectory()) {\r
+ dialog.setFilterPath(f.toString());\r
+ } else if (f.isFile()) {\r
+ IPath path = p.removeLastSegments(1);\r
+ String name = p.lastSegment();\r
+ dialog.setFilterPath(path.toOSString());\r
+ dialog.setFileName(name);\r
+ } else {\r
+ dialog.setFilterPath(f.toString());\r
+ IPath path = p.removeLastSegments(1);\r
+ String name = p.lastSegment();\r
+ f = path.toFile();\r
+ if (f.isDirectory()) {\r
+ dialog.setFilterPath(path.toOSString());\r
+ }\r
+ dialog.setFileName(name);\r
+ }\r
+ }\r
+ String file = dialog.open();\r
+ if (file == null)\r
+ return;\r
+ exportLocation.setText(file);\r
+ validatePage();\r
+ }\r
+ });\r
+ }\r
+\r
+ final Button zoomToFitButton = new Button(container, SWT.CHECK);\r
+ GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo(zoomToFitButton);\r
+ zoomToFitButton.setText("F&it by content");\r
+ zoomToFitButton.setSelection(exportModel.fitContentToPageMargins);\r
+ zoomToFitButton.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ exportModel.fitContentToPageMargins = zoomToFitButton.getSelection();\r
+ }\r
+ });\r
+\r
+ /*\r
+ final Button attachTGButton = new Button(container, SWT.CHECK);\r
+ GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo( attachTGButton );\r
+ attachTGButton.setText("Attach &TG (Importable diagram)");\r
+ attachTGButton.setSelection(exportModel.attachTG);\r
+ attachTGButton.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ exportModel.attachTG = attachTGButton.getSelection();\r
+ }\r
+ });\r
+ */\r
+ \r
+ final Button attachWikiButton = new Button(container, SWT.CHECK);\r
+ GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo( attachWikiButton );\r
+ attachWikiButton.setText("Attach &Wiki page");\r
+ attachWikiButton.setSelection(exportModel.attachWiki);\r
+ attachWikiButton.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ exportModel.attachWiki = attachWikiButton.getSelection();\r
+ }\r
+ });\r
+ \r
+ setControl(container);\r
+ validatePage();\r
+\r
+ scheduleInitializeData(exportModel.selection);\r
+ }\r
+\r
+ private void scheduleInitializeData(final NamedResource modelSelection) {\r
+ display.asyncExec(new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ if (filter.isDisposed())\r
+ return;\r
+\r
+ try {\r
+ initializeData(modelSelection);\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ } catch (InvocationTargetException e) {\r
+ e.getTargetException().printStackTrace();\r
+ } catch (InterruptedException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ });\r
+ }\r
+\r
+ private NamedResource getSelectedModel() {\r
+ int sel = modelSelector.getSelectionIndex();\r
+ if (sel != -1) {\r
+ NamedResource nr = (NamedResource) modelSelector.getData("" + sel);\r
+ return nr;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ private void setExportLocationWithoutNotification(String text) {\r
+ exportLocation.removeModifyListener(exportLocationListener);\r
+ exportLocation.setText(text);\r
+ exportLocation.addModifyListener(exportLocationListener);\r
+ }\r
+\r
+ private Collection<Node> getVisibleNodes() {\r
+ Collection<Node> result = new ArrayList<Node>();\r
+\r
+ Deque<TreeItem> todo = new ArrayDeque<TreeItem>();\r
+ for (TreeItem ti : tree.getTree().getItems()) {\r
+ todo.add(ti);\r
+ }\r
+\r
+ while (!todo.isEmpty()) {\r
+ TreeItem item = todo.removeLast();\r
+ Node node = (Node) item.getData();\r
+ result.add(node);\r
+\r
+ for (TreeItem child : item.getItems()) {\r
+ todo.add(child);\r
+ }\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ private void resetFilterString(String filterString) {\r
+ String patternString = filterStrategy.toPatternString(filterString);\r
+ if (patternString == null) {\r
+ matcher = null;\r
+ } else {\r
+ matcher = Pattern.compile(patternString).matcher("");\r
+ }\r
+ refreshAndExpandTree();\r
+ }\r
+\r
+ private void refreshAndExpandTree() {\r
+ tree.refresh();\r
+ tree.expandAll();\r
+ }\r
+\r
+ private void initializeData(final NamedResource modelSelection) throws DatabaseException, InvocationTargetException, InterruptedException {\r
+ if (modelSelection != null) {\r
+ // Process input selection to find the model/state selected by default.\r
+\r
+ // This may take longer than the user wants to wait without\r
+ // notification.\r
+\r
+ // !PROFILE\r
+ long time = System.nanoTime();\r
+\r
+ getWizard().getContainer().run(true, true, new IRunnableWithProgress() {\r
+ @Override\r
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {\r
+ try {\r
+ final SubMonitor mon = SubMonitor.convert(monitor, "Searching for exportable diagrams...", 100);\r
+ exportModel.sessionContext.getSession().syncRequest(new ReadRequest() {\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ exportModel.nodes = DiagramPrinter.browse(mon.newChild(100), graph, new Resource[] { modelSelection.getResource() });\r
+ }\r
+ });\r
+ } catch (DatabaseException e) {\r
+ throw new InvocationTargetException(e);\r
+ } finally {\r
+ monitor.done();\r
+ }\r
+ }\r
+ });\r
+\r
+ // !PROFILE\r
+ long endTime = System.nanoTime();\r
+ if (exportModel.nodes != null)\r
+ System.out.println("Found " + exportModel.nodes.diagrams.size() + " diagrams in " + ((endTime - time)*1e-9) + " seconds.");\r
+ }\r
+\r
+ // Browsing was canceled by user.\r
+ if (exportModel.nodes == null)\r
+ return;\r
+\r
+ // Setup selected states, select everything by default.\r
+ selectedNodes.clear();\r
+ selectedNodes.addAll(exportModel.nodes.breadthFirstFlatten());\r
+\r
+ tree.setInput(this);\r
+\r
+ for (Node root : exportModel.nodes.roots) {\r
+ tree.setSubtreeChecked(root, true);\r
+ }\r
+\r
+ resetFilterString(filter.getText());\r
+\r
+ modelSelector.removeSelectionListener(modelSelectorListener);\r
+ int selectedIndex = -1;\r
+ for (int i = 0; i < modelSelector.getItemCount(); ++i) {\r
+ Object obj = modelSelector.getData("" + i);\r
+ if (org.simantics.utils.ObjectUtils.objectEquals(obj, modelSelection)) {\r
+ selectedIndex = i;\r
+ }\r
+ }\r
+ if (selectedIndex == -1 && modelSelector.getItemCount() > 0)\r
+ selectedIndex = 0;\r
+ if (selectedIndex != -1)\r
+ modelSelector.select(selectedIndex);\r
+ modelSelector.addSelectionListener(modelSelectorListener);\r
+\r
+ validatePage();\r
+ }\r
+\r
+ void validatePage() {\r
+ //System.out.println("VALIDATE PAGE: " + exportLocationTouchedByUser);\r
+ if (selectedNodes.size() == 0) {\r
+ setMessage("Select the diagrams to export.");\r
+ setErrorMessage(null);\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+\r
+ if (!exportLocationTouchedByUser) {\r
+ String generatedName = null;\r
+ // Generate file name automatically if user hasn't touched the name manually.\r
+ NamedResource nr = getSelectedModel();\r
+ if (nr != null) {\r
+ if (selectedNodes.size() == 1) {\r
+ generatedName = nr.getName() + "-" + selectedNodes.iterator().next().getName();\r
+ } else {\r
+ generatedName = nr.getName();\r
+ }\r
+ }\r
+ //System.out.println("generate name: " + generatedName);\r
+ if (generatedName != null) {\r
+ if (!FileUtils.isValidFileName(generatedName))\r
+ generatedName = (String) Bindings.STR_VARIANT.createUnchecked(Bindings.STRING, generatedName);\r
+ String name = generatedName + ".pdf";\r
+ \r
+ abu:\r
+ if ( !exportModel.recentLocations.isEmpty() ) {\r
+ \r
+ for ( String loc : exportModel.recentLocations )\r
+ {\r
+ if ( loc.endsWith(name) && !loc.equals(name) ) {\r
+ name = loc;\r
+ break abu; \r
+ }\r
+ }\r
+ \r
+ String firstLine = exportModel.recentLocations.iterator().next();\r
+ File f = new File(firstLine); \r
+ File parentFile = f.getParentFile();\r
+ if ( parentFile!=null ) {\r
+ name = new File( f.getParentFile(), name ).getAbsolutePath();\r
+ }\r
+ }\r
+ setExportLocationWithoutNotification(name);\r
+ }\r
+ }\r
+\r
+ String exportLoc = exportLocation.getText();\r
+ if (exportLoc.isEmpty()) {\r
+ setMessage("Select an export target file.");\r
+ setErrorMessage(null);\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+ File file = new File(exportLoc);\r
+ if (file.exists()) {\r
+ if (file.isDirectory()) {\r
+ setErrorMessage("The target already exists and it is a directory.");\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+ if (!file.isFile()) {\r
+ setErrorMessage("The target already exists and it is a not a regular file.");\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+ }\r
+ exportModel.exportLocation = file;\r
+\r
+ int diagramCount = 0;\r
+ for (Node n : selectedNodes)\r
+ if (n.getDiagramResource() != null)\r
+ ++diagramCount;\r
+\r
+ String msg = diagramCount + " diagrams selected for export.";\r
+\r
+ setMessage(msg);\r
+ setErrorMessage(null);\r
+ setPageComplete(true);\r
+ }\r
+\r
+}\r