-package org.simantics.export.ui;\r
-\r
-import java.net.MalformedURLException;\r
-import java.net.URL;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.Comparator;\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import java.util.TreeMap;\r
-\r
-import org.eclipse.jface.resource.ImageDescriptor;\r
-import org.eclipse.jface.resource.JFaceResources;\r
-import org.eclipse.jface.resource.LocalResourceManager;\r
-import org.eclipse.jface.wizard.WizardPage;\r
-import org.eclipse.nebula.widgets.grid.Grid;\r
-import org.eclipse.nebula.widgets.grid.GridColumn;\r
-import org.eclipse.nebula.widgets.grid.GridItem;\r
-import org.eclipse.swt.SWT;\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.graphics.Image;\r
-import org.eclipse.swt.graphics.RGB;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.export.core.ExportContext;\r
-import org.simantics.export.core.error.ExportException;\r
-import org.simantics.export.core.intf.ContentType;\r
-import org.simantics.export.core.intf.Discoverer;\r
-import org.simantics.export.core.intf.Exporter;\r
-import org.simantics.export.core.intf.Format;\r
-import org.simantics.export.core.intf.Publisher;\r
-import org.simantics.export.core.manager.Content;\r
-import org.simantics.export.core.manager.ExportWizardResult;\r
-import org.simantics.export.core.util.ExportQueries;\r
-import org.simantics.export.ui.util.ExportUIQueries;\r
-import org.simantics.utils.datastructures.MapList;\r
-import org.simantics.utils.datastructures.ToStringComparator;\r
-import org.simantics.utils.strings.AlphanumComparator;\r
-import org.simantics.utils.ui.workbench.StringMemento;\r
-\r
-/**\r
- * Show wizard page where content and export format is selected.\r
- *\r
- * @author toni.kalajainen@semantum.fi\r
- */\r
-public class ContentSelectionPage extends WizardPage {\r
- \r
- /** Key for preference setting that contains sub-mementos for each content URI. */\r
- public static final String KEY_FORMAT_SELECTIONS = "org.simantics.modeling.ui.export.wizard.formatSelections";\r
-\r
- // UI stuff\r
- LocalResourceManager resourceManager;\r
- Grid grid;\r
- \r
- // Initial data\r
- ExportContext ctx; \r
- // Hash-code for the initial data\r
- String initialSelectionKey;\r
- Set<Content> initialSelection = new HashSet<Content>();\r
- \r
- // Previous selections\r
- StringMemento formatSelections;\r
- \r
- // Initializations\r
- Collection<String> allModels, selectedModels;\r
- ToStringComparator toStringComparator = new ToStringComparator();\r
- MapList<ContentType, String> content; // ContentType -> Content[]\r
- MapList<ContentType, Format> typeToFormatMap; // ContentType -> Format\r
- MapList<String, ContentType> contentToTypeMap; // uri -> ContentType\r
- Map<String, Map<String, String>> labels; // ContentType -> URI -> Label\r
- MapList<String, String> modelContent; // ModelURI -> ContentURI\r
- \r
- // User selections\r
- List<Content> contentSelection = new ArrayList<Content>();\r
- \r
- public ContentSelectionPage(ExportContext ctx) throws ExportException {\r
- super("Select Content", "Select the PDF Pages and the attachments", null);\r
- this.ctx = ctx;\r
- \r
- init();\r
- }\r
- \r
- void init() throws ExportException {\r
- try {\r
- System.out.println("Found Content Types:");\r
- for ( ContentType ct : ctx.eep.contentTypes() ) {\r
- System.out.println(" "+ct);\r
- }\r
- System.out.println();\r
- \r
- System.out.println("Exporters:");\r
- for ( Exporter ex : ctx.eep.exporters() ) {\r
- System.out.println(" "+ex);\r
- }\r
- System.out.println();\r
-\r
- System.out.println("Formats:");\r
- for ( Format format : ctx.eep.formats() ) {\r
- System.out.println(" "+format);\r
- }\r
- System.out.println();\r
-\r
- System.out.println("Discoverers:");\r
- for ( Discoverer discoverer : ctx.eep.discoverers() ) {\r
- System.out.println(" "+discoverer);\r
- }\r
- System.out.println();\r
- \r
- System.out.println("Publishers:");\r
- for ( Publisher publisher : ctx.eep.publishers() ) {\r
- System.out.println(" "+publisher.id());\r
- }\r
- System.out.println();\r
- \r
- // Organize formats by content types - Filter out ContentTypes that don't have exporter and format.\r
- System.out.println("Mapped ContentTypes to Exporters:");\r
- typeToFormatMap = MapList.use( new TreeMap<ContentType, List<Format>>(toStringComparator) );\r
- for ( ContentType ct : ctx.eep.contentTypes() ) {\r
- for ( Exporter exp : ctx.eep.getExportersForContentType( ct.id() ) ) {\r
- Format format = ctx.eep.getFormat( exp.formatId() );\r
- if ( format==null ) continue;\r
- System.out.println(" "+ct.id()+" -> "+format.fileext());\r
- if (!typeToFormatMap.contains(ct, format)) typeToFormatMap.add(ct, format);\r
- }\r
- }\r
- System.out.println();\r
- \r
- // Discover the models in the project\r
- allModels = ctx.session.syncRequest( ExportUIQueries.models(ctx.project) );\r
-\r
- // Calculate hash for the initial selection\r
- int initialContentHash = 0x52f3a45;\r
- for ( String content : ctx.selection ) {\r
- initialContentHash = 13*initialContentHash + content.hashCode();\r
- }\r
- initialSelectionKey = "InitialSelection-"+initialContentHash;\r
- String sel = ctx.store.get(initialSelectionKey, null);\r
- if ( sel != null ) {\r
- initialSelection = ExportWizardResult.parse(sel);\r
- } else {\r
- // First time wizard was called with this selection.\r
- // Check in\r
- for ( String contentUri : ctx.selection ) {\r
- initialSelection.add( new Content(contentUri, null, "all", null, null, null) );\r
- }\r
- }\r
- \r
- // Choose the models from user interface selection\r
- selectedModels = new ArrayList<String>();\r
- StringBuilder modelsStr = new StringBuilder(); \r
- for ( String content : ctx.selection ) {\r
- for ( String model : allModels ) {\r
- if ( content.equals(model) || content.startsWith(model + "/") ) {\r
- if ( !selectedModels.contains( model ) ) {\r
- selectedModels.add( model );\r
- if ( modelsStr.length()>0 ) modelsStr.append(", ");\r
- modelsStr.append( model );\r
- }\r
- }\r
- }\r
- }\r
- // If user has nothing selected, choose active models\r
- if ( selectedModels.isEmpty() ) selectedModels.addAll( ctx.activeModels );\r
- // If there are no active models, choose all models\r
- if ( selectedModels.isEmpty() ) selectedModels.addAll( allModels );\r
- // UI labels\r
- labels = new HashMap<String, Map<String, String>>(); \r
- labels.put( "model", ctx.session.syncRequest( ExportQueries.labels( selectedModels ) ) ); // Should Model CT be used for labeling? \r
- \r
- // Discover contents\r
- System.out.println("Discovering content: "+modelsStr);\r
- content = MapList.use( new TreeMap<ContentType, List<String>>(toStringComparator) );\r
- contentToTypeMap = MapList.use( new TreeMap<String, List<ContentType>>(toStringComparator) );\r
- modelContent = MapList.use( new TreeMap<String, List<String>>() );\r
- \r
- for ( ContentType ct : typeToFormatMap.getKeys() ) {\r
- System.out.println(" "+ct.label());\r
- for ( Discoverer discoverer : ctx.eep.getDiscoverers( ct.id() )) {\r
- System.out.println(" "+discoverer.toString());\r
- \r
- // Get content Uris\r
- Collection<String> contents = discoverer.discoverContent(ctx, selectedModels);\r
- List<String> contentUris = new ArrayList<String>( contents );\r
-\r
- // Get UI Labels\r
- Map<String, String> lbls = ct.getLabels(ctx, contentUris); \r
- labels.put( ct.id(), lbls );\r
- \r
- // Sort content\r
- IndirectComparator comp = new IndirectComparator();\r
- comp.labels = lbls;\r
- Collections.sort( contentUris, comp );\r
- \r
- for ( String contentId : contentUris ) {\r
- content.add( ct, contentId );\r
- contentToTypeMap.add(contentId, ct);\r
- //modelContent.add(key)\r
- System.out.println(" "+contentId);\r
- }\r
- \r
- }\r
- }\r
- System.out.println();\r
- \r
- \r
- } catch (DatabaseException e) {\r
- throw new ExportException(e);\r
- }\r
-\r
- \r
- }\r
- \r
- @Override\r
- public void createControl(Composite parent) {\r
- grid = new Grid(parent, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);\r
- grid.setHeaderVisible(true);\r
- \r
- resourceManager = new LocalResourceManager(JFaceResources.getResources(), grid);\r
- Color contentTypeColor = resourceManager.createColor( new RGB(245, 245, 252) );\r
- GridColumn column = new GridColumn(grid,SWT.NONE);\r
- column.setTree(true);\r
- column.setText("Name");\r
- column.setWidth(200); \r
-\r
- // "Pagees"\r
- assertColumnIndex(1);\r
- \r
- Format pdfFormat = ctx.eep.getFormat("pdf");\r
- \r
- \r
- ImageDescriptor folderID = null;\r
- try {\r
- URL folderUrl = new URL("platform:/plugin/com.famfamfam.silk/icons/folder.png");\r
- folderID = ImageDescriptor.createFromURL( folderUrl );\r
- } catch (MalformedURLException e) {\r
- e.printStackTrace();\r
- }\r
- \r
- List<GridItem> selectedNodes = new ArrayList<GridItem>();\r
- \r
- // Iterate all models\r
- for ( String modelUri : contentToTypeMap.getKeys() ) {\r
- ContentType modelContentType = null;\r
- for ( ContentType ct : contentToTypeMap.getValues(modelUri) ) {\r
- if ( ct.isModel() ) {\r
- modelContentType = ct;\r
- break;\r
- }\r
- }\r
- if (modelContentType==null) continue;\r
- \r
- // Create Model Node\r
- String modelLabel = labels.get("model").get(modelUri);\r
- GridItem modelNode = newLine(grid, modelLabel, modelUri, modelContentType.id()); \r
- setIcon(modelNode, 0, modelContentType.icon(modelUri));\r
- modelNode.setToolTipText(0, modelUri);\r
- \r
- if ( ctx.selection.contains( modelUri ) ) selectedNodes.add( modelNode );\r
-\r
- // Columns for formats\r
- int column1 = 1;\r
- for ( ContentType ct : contentToTypeMap.getValues(modelUri) ) {\r
- for ( Format format : typeToFormatMap.getValues(ct) ) {\r
- column1++;\r
- assertColumnIndex( column1 );\r
- modelNode.setText(column1, format.fileext());\r
- modelNode.setGrayed(column1, false);\r
- modelNode.setCheckable(column1, true);\r
- modelNode.setData( Integer.toString(column1), \r
- new Content(modelUri, ct.id(), format.id(), modelLabel, format.fileext(), modelUri ) );\r
- modelNode.setChecked(column1, hasInitialSelection(modelUri, format.id()));\r
- modelNode.setToolTipText(column1, format.label());\r
-\r
- ImageDescriptor id = format.icon();\r
- if ( id!=null ) {\r
- Image icon = resourceManager.createImage(id);\r
- if ( icon!=null) modelNode.setImage(column1, icon);\r
- }\r
- }\r
- }\r
- \r
- for ( ContentType ct : content.getKeys() ) \r
- {\r
- if ( ct.isModel() ) continue;\r
- // ContentType Node\r
- GridItem ctNode = newLine(modelNode, ct.label(), modelUri, ct.id());\r
- ctNode.setExpanded( true );\r
- ctNode.setBackground(0, contentTypeColor);\r
- ctNode.setBackground(contentTypeColor);\r
- setIcon(ctNode, 0, folderID);\r
- int contentCount = 0;\r
- ArrayList<Format> contentTypesFormats = new ArrayList<Format>();\r
- \r
- for ( String contentUri : content.getValues(ct) ) {\r
- // WORKAROUND: Should not be based on URI\r
- if ( !contentUri.startsWith(modelUri) ) continue;\r
- // Content Node\r
- String nodeLabel = labels.get(ct.id()).get(contentUri);\r
- GridItem contentNode = newLine(ctNode, nodeLabel, contentUri, ct.id());\r
- contentCount++;\r
- contentNode.setToolTipText(0, contentUri);\r
- setIcon(contentNode, 0, ct.icon(contentUri));\r
- \r
- if ( ctx.selection.contains( contentUri) ) selectedNodes.add( contentNode );\r
- \r
- int columnNumber = 0;\r
- \r
- // PDF Column\r
- List<Format> formats = typeToFormatMap.getValues(ct);\r
- if ( formats.contains( pdfFormat )) {\r
- if ( !contentTypesFormats.contains(pdfFormat) ) contentTypesFormats.add(pdfFormat);\r
- columnNumber++;\r
- assertColumnIndex( columnNumber );\r
- \r
- contentNode.setText(columnNumber, " "+pdfFormat.fileext());\r
- contentNode.setGrayed(columnNumber, false);\r
- contentNode.setCheckable(columnNumber, true);\r
- contentNode.setChecked(columnNumber, hasInitialSelection(contentUri, pdfFormat.id()) );\r
- contentNode.setToolTipText(columnNumber, pdfFormat.label());\r
- setIcon(contentNode, columnNumber, pdfFormat.icon());\r
- \r
- contentNode.setData(\r
- Integer.toString(columnNumber), \r
- new Content(contentUri, ct.id(), pdfFormat.id(), nodeLabel, pdfFormat.fileext(), modelUri ) );\r
- \r
- } else {\r
- if ( !contentTypesFormats.contains(null) ) contentTypesFormats.add(null);\r
- columnNumber++;\r
- assertColumnIndex( columnNumber );\r
- }\r
- \r
- // Attachment Columns\r
- for (Format format : formats ) {\r
- if ( format==pdfFormat ) continue;\r
- if ( !contentTypesFormats.contains(format) ) contentTypesFormats.add(format);\r
- columnNumber++;\r
- assertColumnIndex( columnNumber );\r
- contentNode.setText(columnNumber, " "+format.fileext());\r
- contentNode.setGrayed(columnNumber, false);\r
- contentNode.setCheckable(columnNumber, true);\r
- contentNode.setChecked(columnNumber, hasInitialSelection(contentUri, format.id()) );\r
- contentNode.setToolTipText(columnNumber, format.label()); \r
- setIcon(contentNode, columnNumber, format.icon());\r
-\r
- contentNode.setData(\r
- Integer.toString(columnNumber), \r
- new Content(contentUri, ct.id(), format.id(), nodeLabel, format.fileext(), modelUri ) );\r
- }\r
- }\r
- \r
- // Add the *.pdf buttons\r
- int columnNumber = 0;\r
- Set<GridItem> gis = new HashSet<GridItem>();\r
- for ( Format format : contentTypesFormats ) {\r
- columnNumber++;\r
- ctNode.setBackground(columnNumber, contentTypeColor);\r
- if ( format == null ) continue;\r
- ctChecks.add( new CTCheck(ctNode, columnNumber, format) );\r
- ctNode.setCheckable(columnNumber, true);\r
- ctNode.setGrayed(columnNumber, true);\r
- //setIcon(ctNode, columnNumber, format.icon());\r
- gis.add(ctNode);\r
- //ctNode.setData(Integer.toString(columnNumber), format );\r
- //ctNode.setText(columnNumber, "*"+format.fileext());\r
- }\r
- \r
- if ( contentCount == 0 ) {\r
- ctNode.dispose();\r
- }\r
- \r
- }\r
- modelNode.setExpanded( true );\r
- }\r
- grid.setSelection( selectedNodes.toArray( new GridItem[selectedNodes.size()] ) );\r
- if ( selectedNodes.size()>0 ) {\r
- GridItem first = selectedNodes.get(0);\r
- grid.setFocusItem( first ); \r
- }\r
-\r
- grid.addSelectionListener(ctChecksListener);\r
- /*\r
- grid.addSelectionListener( new SelectionAdapter() {\r
- public void widgetSelected(SelectionEvent e) {\r
- if ( e.item == null || e.item instanceof GridItem==false ) return;\r
- GridItem gi = (GridItem) e.item;\r
- GridColumn column = grid.getColumn( new Point(e.x, e.y) );\r
- if ( column == null ) return;\r
- int columnIndex = -1;\r
- int columnCount = grid.getColumnCount();\r
- for ( int i=0; i<columnCount; i++) {\r
- GridColumn gc = grid.getColumn(i);\r
- if ( gc == column ) {\r
- columnIndex = i;\r
- break;\r
- }\r
- }\r
- System.out.println(e.detail);\r
- System.out.println(e);\r
- System.out.println(columnIndex);\r
- String text = gi.getText(columnIndex);\r
- System.out.println(text);\r
- }\r
- });*/\r
- \r
- setControl(grid);\r
- setPageComplete(true);\r
- }\r
- \r
- void setIcon(GridItem node, int index, ImageDescriptor icon) {\r
- if ( icon == null ) return;\r
- Image image = resourceManager.createImage(icon);\r
- if ( image == null ) return;\r
- node.setImage(index, image);\r
- }\r
- \r
- /**\r
- * Creates column index if doesn't exist.\r
- * Column=2, is "Pages"\r
- * Column>=3, is "Attachement"\r
- * \r
- * @param columnIndex\r
- */\r
- void assertColumnIndex(int columnIndex) {\r
- while ( columnIndex >= grid.getColumnCount() ) {\r
- int cc = grid.getColumnCount();\r
- \r
- GridColumn column = new GridColumn(grid, SWT.CHECK);\r
- column.setText( cc==1?"Pages":"Attachments");\r
- column.setWidth( cc==1?150:200 );\r
- \r
- for (GridItem gi : grid.getItems()) {\r
- gi.setGrayed(cc, true);\r
- gi.setCheckable(cc, false);\r
- }\r
- \r
- } \r
- }\r
- \r
- boolean hasInitialSelection(String uri, String formatId) {\r
- for (Content c : initialSelection) {\r
- if ( !c.url.equals( uri ) ) continue;\r
- if ( c.formatId.equals("all") || c.formatId.equals(formatId) ) return true;\r
- }\r
- return false;\r
- }\r
- \r
- GridItem newLine(Object parent, String label, String url, String contentTypeId) {\r
- GridItem gi = null;\r
- if (parent instanceof Grid) {\r
- gi = new GridItem( (Grid)parent, SWT.NONE);\r
- } else {\r
- gi = new GridItem( (GridItem)parent, SWT.NONE);\r
- }\r
- \r
- gi.setText( label );\r
- if ( url!=null || contentTypeId!=null ) gi.setData( new Content(url, contentTypeId, null, label, null, null) );\r
- for ( int columnIndex=0; columnIndex<grid.getColumnCount(); columnIndex++ ) {\r
- gi.setGrayed(columnIndex, true);\r
- gi.setCheckable(columnIndex, false);\r
- }\r
- \r
- return gi; \r
- }\r
- \r
- public void validatePage() {\r
- List<Content> newContentSelection = new ArrayList<Content>(); \r
- // Get list of content.. something must be checked\r
- int columnWidth = grid.getColumnCount();\r
- Set<String> checkedFormats = new HashSet<String>();\r
- for (GridItem gi : grid.getItems()) {\r
- /*\r
- checkedFormats.clear();\r
- GridItem parentItem = gi.getParentItem();\r
- if ( parentItem!=null ) {\r
- for (int c=0; c<columnWidth; c++) {\r
- if ( parentItem.getChecked(c) ) {\r
- Object data = parentItem.getData( Integer.toString(c) );\r
- if ( data==null || data instanceof Format == false ) continue;\r
- Format format = (Format) data;\r
- checkedFormats.add( format.id() );\r
- }\r
- }\r
- }*/\r
- \r
- for (int c=0; c<columnWidth; c++) { \r
- Object data = gi.getData( Integer.toString(c) );\r
- if ( data==null || data instanceof Content == false ) continue;\r
- Content content = (Content) data; \r
- if ( gi.getChecked(c) || checkedFormats.contains(content.formatId) ) {\r
- newContentSelection.add( content );\r
- }\r
- }\r
- \r
- }\r
- \r
- contentSelection = newContentSelection;\r
- }\r
- \r
- public List<Content> getContentSelection() {\r
- return contentSelection;\r
- }\r
-\r
- public void savePrefs() {\r
- String str = ExportWizardResult.print( getContentSelection() );\r
- ctx.store.put(initialSelectionKey, str);\r
- }\r
- \r
- static class IndirectComparator implements Comparator<String> {\r
- Map<String, String> labels;\r
-\r
- @Override\r
- public int compare(String o1, String o2) {\r
- String l1 = null, l2 = null;\r
- if ( labels != null ) {\r
- l1 = labels.get(o1);\r
- l2 = labels.get(o2);\r
- } \r
- if ( l1 == null ) l1 = o1;\r
- if ( l2 == null ) l2 = o2;\r
- return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(l1, l2);\r
- }\r
- }\r
- \r
- //// Code for following clicks on ContentType format specific checkboxes\r
- List<CTCheck> ctChecks = new ArrayList<CTCheck>();\r
- static class CTCheck {\r
- GridItem gi;\r
- int columnNumber;\r
- Format format;\r
- boolean lastKnownCheckedStatus = false;\r
- CTCheck(GridItem gi, int columnNumber, Format format) {\r
- this.gi = gi;\r
- this.columnNumber = columnNumber;\r
- this.format = format;\r
- }\r
- boolean previousSelection;\r
- boolean checkStatus() {\r
- return gi.getChecked(columnNumber);\r
- }\r
- void setCheck(boolean checked) {\r
- gi.setChecked(columnNumber, checked);\r
- }\r
- }\r
- \r
- SelectionListener ctChecksListener = new SelectionAdapter() {\r
- public void widgetSelected(SelectionEvent e) {\r
- if ( e.item == null || e.item instanceof GridItem==false ) return;\r
- int columnWidth = grid.getColumnCount();\r
- for ( CTCheck cc : ctChecks ) {\r
- boolean checked = cc.checkStatus();\r
- if ( checked == cc.lastKnownCheckedStatus ) continue;\r
- cc.lastKnownCheckedStatus = checked;\r
- \r
- for ( GridItem gi : cc.gi.getItems() ) {\r
- for ( int columnNumber = 0; columnNumber<columnWidth; columnNumber++ ) {\r
- Object data = gi.getData( Integer.toString( columnNumber ) );\r
- if ( data==null || data instanceof Content == false ) continue;\r
- Content content = (Content) data; \r
- if ( !content.formatId.equals( cc.format.id() )) continue;\r
- gi.setChecked(columnNumber, checked);\r
- }\r
- } \r
- }\r
- \r
- }\r
- };\r
- \r
-\r
- \r
-}\r
+package org.simantics.export.ui;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.nebula.widgets.grid.Grid;
+import org.eclipse.nebula.widgets.grid.GridColumn;
+import org.eclipse.nebula.widgets.grid.GridItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.export.core.ExportContext;
+import org.simantics.export.core.error.ExportException;
+import org.simantics.export.core.intf.ContentType;
+import org.simantics.export.core.intf.Discoverer;
+import org.simantics.export.core.intf.Exporter;
+import org.simantics.export.core.intf.Format;
+import org.simantics.export.core.intf.Publisher;
+import org.simantics.export.core.manager.Content;
+import org.simantics.export.core.manager.ExportWizardResult;
+import org.simantics.export.core.util.ExportQueries;
+import org.simantics.export.ui.util.ExportUIQueries;
+import org.simantics.utils.datastructures.MapList;
+import org.simantics.utils.datastructures.ToStringComparator;
+import org.simantics.utils.strings.AlphanumComparator;
+import org.simantics.utils.ui.workbench.StringMemento;
+
+/**
+ * Show wizard page where content and export format is selected.
+ *
+ * @author toni.kalajainen@semantum.fi
+ */
+public class ContentSelectionPage extends WizardPage {
+
+ /** Key for preference setting that contains sub-mementos for each content URI. */
+ public static final String KEY_FORMAT_SELECTIONS = "org.simantics.modeling.ui.export.wizard.formatSelections"; //$NON-NLS-1$
+
+ // UI stuff
+ LocalResourceManager resourceManager;
+ Grid grid;
+
+ // Initial data
+ ExportContext ctx;
+ // Hash-code for the initial data
+ String initialSelectionKey;
+ Set<Content> initialSelection = new HashSet<Content>();
+
+ // Previous selections
+ StringMemento formatSelections;
+
+ // Initializations
+ Collection<String> allModels, selectedModels;
+ ToStringComparator toStringComparator = new ToStringComparator();
+ MapList<ContentType, String> content; // ContentType -> Content[]
+ MapList<ContentType, Format> typeToFormatMap; // ContentType -> Format
+ MapList<String, ContentType> contentToTypeMap; // uri -> ContentType
+ Map<String, Map<String, String>> labels; // ContentType -> URI -> Label
+ MapList<String, String> modelContent; // ModelURI -> ContentURI
+
+ // User selections
+ List<Content> contentSelection = new ArrayList<Content>();
+
+ public ContentSelectionPage(ExportContext ctx) throws ExportException {
+ super(Messages.ContentSelectionPage_SelectContent, Messages.ContentSelectionPage_SelectContentDescription, null);
+ this.ctx = ctx;
+
+ init();
+ }
+
+ void init() throws ExportException {
+ try {
+ System.out.println("Found Content Types:"); //$NON-NLS-1$
+ for ( ContentType ct : ctx.eep.contentTypes() ) {
+ System.out.println(" "+ct); //$NON-NLS-1$
+ }
+ System.out.println();
+
+ System.out.println("Exporters:"); //$NON-NLS-1$
+ for ( Exporter ex : ctx.eep.exporters() ) {
+ System.out.println(" "+ex); //$NON-NLS-1$
+ }
+ System.out.println();
+
+ System.out.println("Formats:"); //$NON-NLS-1$
+ for ( Format format : ctx.eep.formats() ) {
+ System.out.println(" "+format); //$NON-NLS-1$
+ }
+ System.out.println();
+
+ System.out.println("Discoverers:"); //$NON-NLS-1$
+ for ( Discoverer discoverer : ctx.eep.discoverers() ) {
+ System.out.println(" "+discoverer); //$NON-NLS-1$
+ }
+ System.out.println();
+
+ System.out.println("Publishers:"); //$NON-NLS-1$
+ for ( Publisher publisher : ctx.eep.publishers() ) {
+ System.out.println(" "+publisher.id()); //$NON-NLS-1$
+ }
+ System.out.println();
+
+ // Organize formats by content types - Filter out ContentTypes that don't have exporter and format.
+ System.out.println("Mapped ContentTypes to Exporters:"); //$NON-NLS-1$
+ typeToFormatMap = MapList.use( new TreeMap<ContentType, List<Format>>(toStringComparator) );
+ for ( ContentType ct : ctx.eep.contentTypes() ) {
+ for ( Exporter exp : ctx.eep.getExportersForContentType( ct.id() ) ) {
+ Format format = ctx.eep.getFormat( exp.formatId() );
+ if ( format==null ) continue;
+ System.out.println(" "+ct.id()+" -> "+format.fileext()); //$NON-NLS-1$ //$NON-NLS-2$
+ if (!typeToFormatMap.contains(ct, format)) typeToFormatMap.add(ct, format);
+ }
+ }
+ System.out.println();
+
+ // Discover the models in the project
+ allModels = ctx.session.syncRequest( ExportUIQueries.models(ctx.project) );
+
+ // Calculate hash for the initial selection
+ int initialContentHash = 0x52f3a45;
+ for ( String content : ctx.selection ) {
+ initialContentHash = 13*initialContentHash + content.hashCode();
+ }
+ initialSelectionKey = "InitialSelection-"+initialContentHash; //$NON-NLS-1$
+ String sel = ctx.store.get(initialSelectionKey, null);
+ if ( sel != null ) {
+ initialSelection = ExportWizardResult.parse(sel);
+ } else {
+ // First time wizard was called with this selection.
+ // Check in
+ for ( String contentUri : ctx.selection ) {
+ initialSelection.add( new Content(contentUri, null, "all", null, null, null) ); //$NON-NLS-1$
+ }
+ }
+
+ // Choose the models from user interface selection
+ selectedModels = new ArrayList<String>();
+ StringBuilder modelsStr = new StringBuilder();
+ for ( String content : ctx.selection ) {
+ for ( String model : allModels ) {
+ if ( content.equals(model) || content.startsWith(model + "/") ) { //$NON-NLS-1$
+ if ( !selectedModels.contains( model ) ) {
+ selectedModels.add( model );
+ if ( modelsStr.length()>0 ) modelsStr.append(", "); //$NON-NLS-1$
+ modelsStr.append( model );
+ }
+ }
+ }
+ }
+ // If user has nothing selected, choose active models
+ if ( selectedModels.isEmpty() ) selectedModels.addAll( ctx.activeModels );
+ // If there are no active models, choose all models
+ if ( selectedModels.isEmpty() ) selectedModels.addAll( allModels );
+ // UI labels
+ labels = new HashMap<String, Map<String, String>>();
+ labels.put( "model", ctx.session.syncRequest( ExportQueries.labels( selectedModels ) ) ); // Should Model CT be used for labeling? //$NON-NLS-1$
+
+ // Discover contents
+ System.out.println("Discovering content: "+modelsStr); //$NON-NLS-1$
+ content = MapList.use( new TreeMap<ContentType, List<String>>(toStringComparator) );
+ contentToTypeMap = MapList.use( new TreeMap<String, List<ContentType>>(toStringComparator) );
+ modelContent = MapList.use( new TreeMap<String, List<String>>() );
+
+ for ( ContentType ct : typeToFormatMap.getKeys() ) {
+ System.out.println(" "+ct.label()); //$NON-NLS-1$
+ for ( Discoverer discoverer : ctx.eep.getDiscoverers( ct.id() )) {
+ System.out.println(" "+discoverer.toString()); //$NON-NLS-1$
+
+ // Get content Uris
+ Collection<String> contents = discoverer.discoverContent(ctx, selectedModels);
+ List<String> contentUris = new ArrayList<String>( contents );
+
+ // Get UI Labels
+ Map<String, String> lbls = ct.getLabels(ctx, contentUris);
+ labels.put( ct.id(), lbls );
+
+ // Sort content
+ IndirectComparator comp = new IndirectComparator();
+ comp.labels = lbls;
+ Collections.sort( contentUris, comp );
+
+ for ( String contentId : contentUris ) {
+ content.add( ct, contentId );
+ contentToTypeMap.add(contentId, ct);
+ //modelContent.add(key)
+ System.out.println(" "+contentId); //$NON-NLS-1$
+ }
+
+ }
+ }
+ System.out.println();
+
+
+ } catch (DatabaseException e) {
+ throw new ExportException(e);
+ }
+
+
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ grid = new Grid(parent, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
+ grid.setHeaderVisible(true);
+
+ resourceManager = new LocalResourceManager(JFaceResources.getResources(), grid);
+ Color contentTypeColor = resourceManager.createColor( new RGB(245, 245, 252) );
+ GridColumn column = new GridColumn(grid,SWT.NONE);
+ column.setTree(true);
+ column.setText(Messages.ContentSelectionPage_Name);
+ column.setWidth(200);
+
+ // "Pagees"
+ assertColumnIndex(1);
+
+ Format pdfFormat = ctx.eep.getFormat("pdf"); //$NON-NLS-1$
+
+
+ ImageDescriptor folderID = null;
+ try {
+ URL folderUrl = new URL("platform:/plugin/com.famfamfam.silk/icons/folder.png"); //$NON-NLS-1$
+ folderID = ImageDescriptor.createFromURL( folderUrl );
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+
+ List<GridItem> selectedNodes = new ArrayList<GridItem>();
+
+ // Iterate all models
+ for ( String modelUri : contentToTypeMap.getKeys() ) {
+ ContentType modelContentType = null;
+ for ( ContentType ct : contentToTypeMap.getValues(modelUri) ) {
+ if ( ct.isModel() ) {
+ modelContentType = ct;
+ break;
+ }
+ }
+ if (modelContentType==null) continue;
+
+ // Create Model Node
+ String modelLabel = labels.get("model").get(modelUri); //$NON-NLS-1$
+ GridItem modelNode = newLine(grid, modelLabel, modelUri, modelContentType.id());
+ setIcon(modelNode, 0, modelContentType.icon(modelUri));
+ modelNode.setToolTipText(0, modelUri);
+
+ if ( ctx.selection.contains( modelUri ) ) selectedNodes.add( modelNode );
+
+ // Columns for formats
+ int column1 = 1;
+ for ( ContentType ct : contentToTypeMap.getValues(modelUri) ) {
+ for ( Format format : typeToFormatMap.getValues(ct) ) {
+ column1++;
+ assertColumnIndex( column1 );
+ modelNode.setText(column1, format.fileext());
+ modelNode.setGrayed(column1, false);
+ modelNode.setCheckable(column1, true);
+ modelNode.setData( Integer.toString(column1),
+ new Content(modelUri, ct.id(), format.id(), modelLabel, format.fileext(), modelUri ) );
+ modelNode.setChecked(column1, hasInitialSelection(modelUri, format.id()));
+ modelNode.setToolTipText(column1, format.label());
+
+ ImageDescriptor id = format.icon();
+ if ( id!=null ) {
+ Image icon = resourceManager.createImage(id);
+ if ( icon!=null) modelNode.setImage(column1, icon);
+ }
+ }
+ }
+
+ for ( ContentType ct : content.getKeys() )
+ {
+ if ( ct.isModel() ) continue;
+ // ContentType Node
+ GridItem ctNode = newLine(modelNode, ct.label(), modelUri, ct.id());
+ ctNode.setExpanded( true );
+ ctNode.setBackground(0, contentTypeColor);
+ ctNode.setBackground(contentTypeColor);
+ setIcon(ctNode, 0, folderID);
+ int contentCount = 0;
+ ArrayList<Format> contentTypesFormats = new ArrayList<Format>();
+
+ for ( String contentUri : content.getValues(ct) ) {
+ // WORKAROUND: Should not be based on URI
+ if ( !contentUri.startsWith(modelUri) ) continue;
+ // Content Node
+ String nodeLabel = labels.get(ct.id()).get(contentUri);
+ GridItem contentNode = newLine(ctNode, nodeLabel, contentUri, ct.id());
+ contentCount++;
+ contentNode.setToolTipText(0, contentUri);
+ setIcon(contentNode, 0, ct.icon(contentUri));
+
+ if ( ctx.selection.contains( contentUri) ) selectedNodes.add( contentNode );
+
+ int columnNumber = 0;
+
+ // PDF Column
+ List<Format> formats = typeToFormatMap.getValues(ct);
+ if ( formats.contains( pdfFormat )) {
+ if ( !contentTypesFormats.contains(pdfFormat) ) contentTypesFormats.add(pdfFormat);
+ columnNumber++;
+ assertColumnIndex( columnNumber );
+
+ contentNode.setText(columnNumber, " "+pdfFormat.fileext()); //$NON-NLS-1$
+ contentNode.setGrayed(columnNumber, false);
+ contentNode.setCheckable(columnNumber, true);
+ contentNode.setChecked(columnNumber, hasInitialSelection(contentUri, pdfFormat.id()) );
+ contentNode.setToolTipText(columnNumber, pdfFormat.label());
+ setIcon(contentNode, columnNumber, pdfFormat.icon());
+
+ contentNode.setData(
+ Integer.toString(columnNumber),
+ new Content(contentUri, ct.id(), pdfFormat.id(), nodeLabel, pdfFormat.fileext(), modelUri ) );
+
+ } else {
+ if ( !contentTypesFormats.contains(null) ) contentTypesFormats.add(null);
+ columnNumber++;
+ assertColumnIndex( columnNumber );
+ }
+
+ // Attachment Columns
+ for (Format format : formats ) {
+ if ( format==pdfFormat ) continue;
+ if ( !contentTypesFormats.contains(format) ) contentTypesFormats.add(format);
+ columnNumber++;
+ assertColumnIndex( columnNumber );
+ contentNode.setText(columnNumber, " "+format.fileext()); //$NON-NLS-1$
+ contentNode.setGrayed(columnNumber, false);
+ contentNode.setCheckable(columnNumber, true);
+ contentNode.setChecked(columnNumber, hasInitialSelection(contentUri, format.id()) );
+ contentNode.setToolTipText(columnNumber, format.label());
+ setIcon(contentNode, columnNumber, format.icon());
+
+ contentNode.setData(
+ Integer.toString(columnNumber),
+ new Content(contentUri, ct.id(), format.id(), nodeLabel, format.fileext(), modelUri ) );
+ }
+ }
+
+ // Add the *.pdf buttons
+ int columnNumber = 0;
+ Set<GridItem> gis = new HashSet<GridItem>();
+ for ( Format format : contentTypesFormats ) {
+ columnNumber++;
+ ctNode.setBackground(columnNumber, contentTypeColor);
+ if ( format == null ) continue;
+ ctChecks.add( new CTCheck(ctNode, columnNumber, format) );
+ ctNode.setCheckable(columnNumber, true);
+ ctNode.setGrayed(columnNumber, true);
+ //setIcon(ctNode, columnNumber, format.icon());
+ gis.add(ctNode);
+ //ctNode.setData(Integer.toString(columnNumber), format );
+ //ctNode.setText(columnNumber, "*"+format.fileext());
+ }
+
+ if ( contentCount == 0 ) {
+ ctNode.dispose();
+ }
+
+ }
+ modelNode.setExpanded( true );
+ }
+ grid.setSelection( selectedNodes.toArray( new GridItem[selectedNodes.size()] ) );
+ if ( selectedNodes.size()>0 ) {
+ GridItem first = selectedNodes.get(0);
+ grid.setFocusItem( first );
+ }
+
+ grid.addSelectionListener(ctChecksListener);
+ /*
+ grid.addSelectionListener( new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if ( e.item == null || e.item instanceof GridItem==false ) return;
+ GridItem gi = (GridItem) e.item;
+ GridColumn column = grid.getColumn( new Point(e.x, e.y) );
+ if ( column == null ) return;
+ int columnIndex = -1;
+ int columnCount = grid.getColumnCount();
+ for ( int i=0; i<columnCount; i++) {
+ GridColumn gc = grid.getColumn(i);
+ if ( gc == column ) {
+ columnIndex = i;
+ break;
+ }
+ }
+ System.out.println(e.detail);
+ System.out.println(e);
+ System.out.println(columnIndex);
+ String text = gi.getText(columnIndex);
+ System.out.println(text);
+ }
+ });*/
+
+ setControl(grid);
+ setPageComplete(true);
+ }
+
+ void setIcon(GridItem node, int index, ImageDescriptor icon) {
+ if ( icon == null ) return;
+ Image image = resourceManager.createImage(icon);
+ if ( image == null ) return;
+ node.setImage(index, image);
+ }
+
+ /**
+ * Creates column index if doesn't exist.
+ * Column=2, is "Pages"
+ * Column>=3, is "Attachement"
+ *
+ * @param columnIndex
+ */
+ void assertColumnIndex(int columnIndex) {
+ while ( columnIndex >= grid.getColumnCount() ) {
+ int cc = grid.getColumnCount();
+
+ GridColumn column = new GridColumn(grid, SWT.CHECK);
+ column.setText( cc==1?Messages.ContentSelectionPage_Pages:Messages.ContentSelectionPage_Attachments);
+ column.setWidth( cc==1?150:200 );
+
+ for (GridItem gi : grid.getItems()) {
+ gi.setGrayed(cc, true);
+ gi.setCheckable(cc, false);
+ }
+
+ }
+ }
+
+ boolean hasInitialSelection(String uri, String formatId) {
+ for (Content c : initialSelection) {
+ if ( !c.url.equals( uri ) ) continue;
+ if ( c.formatId.equals("all") || c.formatId.equals(formatId) ) return true; //$NON-NLS-1$
+ }
+ return false;
+ }
+
+ GridItem newLine(Object parent, String label, String url, String contentTypeId) {
+ GridItem gi = null;
+ if (parent instanceof Grid) {
+ gi = new GridItem( (Grid)parent, SWT.NONE);
+ } else {
+ gi = new GridItem( (GridItem)parent, SWT.NONE);
+ }
+
+ gi.setText( label );
+ if ( url!=null || contentTypeId!=null ) gi.setData( new Content(url, contentTypeId, null, label, null, null) );
+ for ( int columnIndex=0; columnIndex<grid.getColumnCount(); columnIndex++ ) {
+ gi.setGrayed(columnIndex, true);
+ gi.setCheckable(columnIndex, false);
+ }
+
+ return gi;
+ }
+
+ public void validatePage() {
+ List<Content> newContentSelection = new ArrayList<Content>();
+ // Get list of content.. something must be checked
+ int columnWidth = grid.getColumnCount();
+ Set<String> checkedFormats = new HashSet<String>();
+ for (GridItem gi : grid.getItems()) {
+ /*
+ checkedFormats.clear();
+ GridItem parentItem = gi.getParentItem();
+ if ( parentItem!=null ) {
+ for (int c=0; c<columnWidth; c++) {
+ if ( parentItem.getChecked(c) ) {
+ Object data = parentItem.getData( Integer.toString(c) );
+ if ( data==null || data instanceof Format == false ) continue;
+ Format format = (Format) data;
+ checkedFormats.add( format.id() );
+ }
+ }
+ }*/
+
+ for (int c=0; c<columnWidth; c++) {
+ Object data = gi.getData( Integer.toString(c) );
+ if ( data==null || data instanceof Content == false ) continue;
+ Content content = (Content) data;
+ if ( gi.getChecked(c) || checkedFormats.contains(content.formatId) ) {
+ newContentSelection.add( content );
+ }
+ }
+
+ }
+
+ contentSelection = newContentSelection;
+ }
+
+ public List<Content> getContentSelection() {
+ return contentSelection;
+ }
+
+ public void savePrefs() {
+ String str = ExportWizardResult.print( getContentSelection() );
+ ctx.store.put(initialSelectionKey, str);
+ }
+
+ static class IndirectComparator implements Comparator<String> {
+ Map<String, String> labels;
+
+ @Override
+ public int compare(String o1, String o2) {
+ String l1 = null, l2 = null;
+ if ( labels != null ) {
+ l1 = labels.get(o1);
+ l2 = labels.get(o2);
+ }
+ if ( l1 == null ) l1 = o1;
+ if ( l2 == null ) l2 = o2;
+ return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(l1, l2);
+ }
+ }
+
+ //// Code for following clicks on ContentType format specific checkboxes
+ List<CTCheck> ctChecks = new ArrayList<CTCheck>();
+ static class CTCheck {
+ GridItem gi;
+ int columnNumber;
+ Format format;
+ boolean lastKnownCheckedStatus = false;
+ CTCheck(GridItem gi, int columnNumber, Format format) {
+ this.gi = gi;
+ this.columnNumber = columnNumber;
+ this.format = format;
+ }
+ boolean previousSelection;
+ boolean checkStatus() {
+ return gi.getChecked(columnNumber);
+ }
+ void setCheck(boolean checked) {
+ gi.setChecked(columnNumber, checked);
+ }
+ }
+
+ SelectionListener ctChecksListener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if ( e.item == null || e.item instanceof GridItem==false ) return;
+ int columnWidth = grid.getColumnCount();
+ for ( CTCheck cc : ctChecks ) {
+ boolean checked = cc.checkStatus();
+ if ( checked == cc.lastKnownCheckedStatus ) continue;
+ cc.lastKnownCheckedStatus = checked;
+
+ for ( GridItem gi : cc.gi.getItems() ) {
+ for ( int columnNumber = 0; columnNumber<columnWidth; columnNumber++ ) {
+ Object data = gi.getData( Integer.toString( columnNumber ) );
+ if ( data==null || data instanceof Content == false ) continue;
+ Content content = (Content) data;
+ if ( !content.formatId.equals( cc.format.id() )) continue;
+ gi.setChecked(columnNumber, checked);
+ }
+ }
+ }
+
+ }
+ };
+
+
+
+}