X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.export.ui%2Fsrc%2Forg%2Fsimantics%2Fexport%2Fui%2FContentSelectionPage.java;fp=bundles%2Forg.simantics.export.ui%2Fsrc%2Forg%2Fsimantics%2Fexport%2Fui%2FContentSelectionPage.java;h=d86484e1fd8ad696f365256dce151f6f1cf4abbe;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.export.ui/src/org/simantics/export/ui/ContentSelectionPage.java b/bundles/org.simantics.export.ui/src/org/simantics/export/ui/ContentSelectionPage.java new file mode 100644 index 000000000..d86484e1f --- /dev/null +++ b/bundles/org.simantics.export.ui/src/org/simantics/export/ui/ContentSelectionPage.java @@ -0,0 +1,577 @@ +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"; + + // UI stuff + LocalResourceManager resourceManager; + Grid grid; + + // Initial data + ExportContext ctx; + // Hash-code for the initial data + String initialSelectionKey; + Set initialSelection = new HashSet(); + + // Previous selections + StringMemento formatSelections; + + // Initializations + Collection allModels, selectedModels; + ToStringComparator toStringComparator = new ToStringComparator(); + MapList content; // ContentType -> Content[] + MapList typeToFormatMap; // ContentType -> Format + MapList contentToTypeMap; // uri -> ContentType + Map> labels; // ContentType -> URI -> Label + MapList modelContent; // ModelURI -> ContentURI + + // User selections + List contentSelection = new ArrayList(); + + public ContentSelectionPage(ExportContext ctx) throws ExportException { + super("Select Content", "Select the PDF Pages and the attachments", null); + this.ctx = ctx; + + init(); + } + + void init() throws ExportException { + try { + System.out.println("Found Content Types:"); + for ( ContentType ct : ctx.eep.contentTypes() ) { + System.out.println(" "+ct); + } + System.out.println(); + + System.out.println("Exporters:"); + for ( Exporter ex : ctx.eep.exporters() ) { + System.out.println(" "+ex); + } + System.out.println(); + + System.out.println("Formats:"); + for ( Format format : ctx.eep.formats() ) { + System.out.println(" "+format); + } + System.out.println(); + + System.out.println("Discoverers:"); + for ( Discoverer discoverer : ctx.eep.discoverers() ) { + System.out.println(" "+discoverer); + } + System.out.println(); + + System.out.println("Publishers:"); + for ( Publisher publisher : ctx.eep.publishers() ) { + System.out.println(" "+publisher.id()); + } + 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:"); + typeToFormatMap = MapList.use( new TreeMap>(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()); + 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; + 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) ); + } + } + + // Choose the models from user interface selection + selectedModels = new ArrayList(); + StringBuilder modelsStr = new StringBuilder(); + for ( String content : ctx.selection ) { + for ( String model : allModels ) { + if ( content.equals(model) || content.startsWith(model + "/") ) { + if ( !selectedModels.contains( model ) ) { + selectedModels.add( model ); + if ( modelsStr.length()>0 ) modelsStr.append(", "); + 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>(); + labels.put( "model", ctx.session.syncRequest( ExportQueries.labels( selectedModels ) ) ); // Should Model CT be used for labeling? + + // Discover contents + System.out.println("Discovering content: "+modelsStr); + content = MapList.use( new TreeMap>(toStringComparator) ); + contentToTypeMap = MapList.use( new TreeMap>(toStringComparator) ); + modelContent = MapList.use( new TreeMap>() ); + + for ( ContentType ct : typeToFormatMap.getKeys() ) { + System.out.println(" "+ct.label()); + for ( Discoverer discoverer : ctx.eep.getDiscoverers( ct.id() )) { + System.out.println(" "+discoverer.toString()); + + // Get content Uris + Collection contents = discoverer.discoverContent(ctx, selectedModels); + List contentUris = new ArrayList( contents ); + + // Get UI Labels + Map 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); + } + + } + } + 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("Name"); + column.setWidth(200); + + // "Pagees" + assertColumnIndex(1); + + Format pdfFormat = ctx.eep.getFormat("pdf"); + + + ImageDescriptor folderID = null; + try { + URL folderUrl = new URL("platform:/plugin/com.famfamfam.silk/icons/folder.png"); + folderID = ImageDescriptor.createFromURL( folderUrl ); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + + List selectedNodes = new ArrayList(); + + // 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); + 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 contentTypesFormats = new ArrayList(); + + 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 formats = typeToFormatMap.getValues(ct); + if ( formats.contains( pdfFormat )) { + if ( !contentTypesFormats.contains(pdfFormat) ) contentTypesFormats.add(pdfFormat); + columnNumber++; + assertColumnIndex( columnNumber ); + + contentNode.setText(columnNumber, " "+pdfFormat.fileext()); + 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()); + 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 gis = new HashSet(); + 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=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?"Pages":"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; + } + 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 newContentSelection = new ArrayList(); + // Get list of content.. something must be checked + int columnWidth = grid.getColumnCount(); + Set checkedFormats = new HashSet(); + for (GridItem gi : grid.getItems()) { + /* + checkedFormats.clear(); + GridItem parentItem = gi.getParentItem(); + if ( parentItem!=null ) { + for (int c=0; c getContentSelection() { + return contentSelection; + } + + public void savePrefs() { + String str = ExportWizardResult.print( getContentSelection() ); + ctx.store.put(initialSelectionKey, str); + } + + static class IndirectComparator implements Comparator { + Map 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 ctChecks = new ArrayList(); + 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