]> gerrit.simantics Code Review - simantics/district.git/commitdiff
Enhancements to district functionalities and code 15/615/1
authorjsimomaa <jani.simomaa@gmail.com>
Mon, 15 May 2017 11:06:05 +0000 (14:06 +0300)
committerjsimomaa <jani.simomaa@gmail.com>
Mon, 15 May 2017 11:06:05 +0000 (14:06 +0300)
Change-Id: Ia388a879d9624724a66f6ce7c7d7891e553bb172

31 files changed:
org.simantics.district.imports.ui/META-INF/MANIFEST.MF
org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportModel.java
org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizard.java
org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizardFirstPage.java [new file with mode: 0644]
org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizardPage.java
org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/ComponentMappingPage.java [new file with mode: 0644]
org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/controls/DynamicComboFieldEditor.java [new file with mode: 0644]
org.simantics.district.imports/src/org/simantics/district/imports/DistrictImportUtils.java
org.simantics.district.maps/src/org/simantics/maps/MapScalingTransform.java [new file with mode: 0644]
org.simantics.district.maps/src/org/simantics/maps/sg/MapNode.java
org.simantics.district.network.ui.ontology/graph.tg
org.simantics.district.network.ui.ontology/graph/DistrictNetworkUI.pgraph
org.simantics.district.network.ui/META-INF/MANIFEST.MF
org.simantics.district.network.ui/fragment.e4xmi
org.simantics.district.network.ui/src/org/simantics/district/network/ui/DNEdgeBuilder.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictDiagramViewer.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictNetworkEdge.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/adapters/DistrictNetworkEdgeElement.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/adapters/DistrictNetworkEdgeElementFactory.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/contributions/ChangeMappingTypeHandler.java [new file with mode: 0644]
org.simantics.district.network.ui/src/org/simantics/district/network/ui/function/Functions.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkEdgeNode.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkVertexNode.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/MapRulerNode.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/NetworkDrawingNode.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DNTranslateMode.java
org.simantics.district.network/META-INF/MANIFEST.MF
org.simantics.district.network/src/org/simantics/district/network/DistrictNetworkUtil.java
org.simantics.district.network/src/org/simantics/district/network/ModelledCRS.java
org.simantics.maps.server.ui/src/org/simantics/maps/server/ui/Activator.java
org.simantics.maps.server/src/org/simantics/district/maps/server/Activator.java

index 48019c70ff4e951999eb0f462c1c3b3470486e5a..b7d0aa63ca049a418af0ad51c96b214db13c73ab 100644 (file)
@@ -10,5 +10,11 @@ Require-Bundle: org.eclipse.ui.ide,
  org.simantics.district.imports;bundle-version="1.0.0",
  org.simantics.db,
  org.simantics.district.geotools;bundle-version="1.0.0",
- org.simantics.district.network.ui;bundle-version="1.0.0"
+ org.simantics.district.network.ui;bundle-version="1.0.0",
+ org.simantics.db.common,
+ org.simantics,
+ org.simantics.diagram.ontology,
+ org.simantics.modeling.ontology,
+ org.simantics.district.network,
+ org.simantics.district.network.ontology
 Bundle-ActivationPolicy: lazy
index 1521a926c233005eef708058f478dbd5f8641886..53de5cfe27714ad2be556b34b065a564174a7bfe 100644 (file)
@@ -3,20 +3,46 @@ package org.simantics.district.imports.ui;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.csv.CSVRecord;
+import org.simantics.db.Resource;
 import org.simantics.district.imports.DistrictImportUtils;
 import org.simantics.district.imports.DistrictImportUtils.CSVHeader;
 
 public class CSVImportModel {
 
+    // First page fills these
+    private Resource targetDiagram;
     private Path source;
+    
+    // Second page fills these
     private char delimiter;
     private boolean read;
     private Map<String, Character> delimiters;
     private Path wktFile;
+    
+    // Vertex import
+    private int xCoordIndex = -1;
+    private int yCoordIndex = -1;
+    private int zCoordIndex = -1;
+    
+    // Edge import
+    private int startXCoordIndex = -1;
+    private int startYCoordIndex = -1;
+    private int startZCoordIndex = -1;
+    private int endXCoordIndex = -1;
+    private int endYCoordIndex = -1;
+    private int endZCoordIndex = -1;
+    
+    // common
+    private int componentMappingIndex = -1;
+    private Map<String, Resource> componentMappings = new HashMap<>();
+    private boolean isVertexImport;
+    
+    // Third page
 
     public CSVImportModel() {
         delimiters = DistrictImportUtils.getSupportedCSVDelimiterFormats();
@@ -87,4 +113,113 @@ public class CSVImportModel {
     public Path getWKTFile() {
         return wktFile;
     }
+
+    public int getXCoordIndex() {
+        return xCoordIndex;
+    }
+
+    public void setXCoordIndex(int xCoordIndex) {
+        this.xCoordIndex = xCoordIndex;
+    }
+
+    public int getYCoordIndex() {
+        return yCoordIndex;
+    }
+
+    public void setYCoordIndex(int yCoordIndex) {
+        this.yCoordIndex = yCoordIndex;
+    }
+
+    public int getZCoordIndex() {
+        return zCoordIndex;
+    }
+
+    public void setZCoordIndex(int zCoordIndex) {
+        this.zCoordIndex = zCoordIndex;
+    }
+
+    public int getComponentMappingIndex() {
+        return componentMappingIndex;
+    }
+    
+    public void setComponentMappingIndex(int componentMappingIndex) {
+        this.componentMappingIndex = componentMappingIndex;
+    }
+
+    public void setParentDiagram(Resource diagram) {
+        this.targetDiagram = diagram;
+    }
+
+    public Resource getParentDiagram() {
+        return targetDiagram;
+    }
+
+    public void setWKTFile(Path wktFile) {
+        this.wktFile = wktFile;
+    }
+
+    public void setComponentMappings(String value, Resource resource) {
+        componentMappings.put(value, resource);
+    }
+
+    public Map<String, Resource> getComponentMappings() {
+        return componentMappings;
+    }
+
+    public boolean isVertexImport() {
+        return isVertexImport;
+    }
+    
+    public void setVertexImport(boolean isVertexImport) {
+        this.isVertexImport = isVertexImport;
+    }
+
+    public void setStartXCoordIndex(int parseInt) {
+        this.startXCoordIndex = parseInt;
+    }
+    
+    public int getStartXCoordIndex() {
+        return startXCoordIndex;
+    }
+
+    public void setStartYCoordIndex(int parseInt) {
+        this.startYCoordIndex = parseInt;
+    }
+    
+    public int getStartYCoordIndex() {
+        return startYCoordIndex;
+    }
+
+    public void setStartZCoordIndex(int parseInt) {
+        this.startZCoordIndex = parseInt;
+    }
+    
+    public int getStartZCoordIndex() {
+        return startZCoordIndex;
+    }
+
+    public void setEndXCoordIndex(int parseInt) {
+        this.endXCoordIndex = parseInt;
+    }
+    
+    public int getEndXCoordIndex() {
+        return endXCoordIndex;
+    }
+
+    public void setEndYCoordIndex(int parseInt) {
+        this.endYCoordIndex = parseInt;
+    }
+    
+    public int getEndYCoordIndex() {
+        return endYCoordIndex;
+    }
+
+    public void setEndZCoordIndex(int parseInt) {
+        this.endZCoordIndex = parseInt;
+    }
+    
+    public int getEndZCoordIndex() {
+        return endZCoordIndex;
+    }
+
 }
index 7a29e7505788c6b603a34f9dbf0c7cc76f30b896..58fd168c8db9f94517a8a2770e1b2f161ea560a7 100644 (file)
@@ -9,10 +9,24 @@ import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.wizard.Wizard;
 import org.eclipse.ui.IImportWizard;
 import org.eclipse.ui.IWorkbench;
+import org.geotools.geometry.DirectPosition2D;
 import org.geotools.referencing.CRS;
+import org.opengis.geometry.DirectPosition;
+import org.opengis.geometry.MismatchedDimensionException;
 import org.opengis.referencing.FactoryException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
+import org.simantics.Simantics;
+import org.simantics.databoard.Bindings;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.request.Write;
 import org.simantics.district.imports.DistrictImportUtils;
+import org.simantics.district.network.DistrictNetworkUtil;
+import org.simantics.district.network.ontology.DistrictNetworkResource;
+import org.simantics.district.network.ui.DNEdgeBuilder;
 
 public class CSVImportWizard extends Wizard implements IImportWizard {
 
@@ -26,7 +40,9 @@ public class CSVImportWizard extends Wizard implements IImportWizard {
     @Override
     public void init(IWorkbench workbench, IStructuredSelection selection) {
         model = new CSVImportModel();
+        addPage(new CSVImportWizardFirstPage(model));
         addPage(new CSVImportWizardPage(model));
+        addPage(new ComponentMappingPage(model));
     }
     
     @Override
@@ -41,17 +57,87 @@ public class CSVImportWizard extends Wizard implements IImportWizard {
             
             Path wktFile = model.getWKTFile();
             
+            int xCoordColumnIndex = model.getXCoordIndex();
+            int yCoordColumnIndex = model.getYCoordIndex();
+            int zCoordColumnIndex = model.getZCoordIndex();
+            
+            int startXCoordColumnIndex = model.getStartXCoordIndex();
+            int startYCoordColumnIndex = model.getStartYCoordIndex();
+            int startZValueColumnIndex = model.getStartZCoordIndex();
+            int endXCoordColumnIndex = model.getEndXCoordIndex();
+            int endYCoordColumnIndex = model.getEndYCoordIndex();
+            int endZValueColumnIndex = model.getEndZCoordIndex();
+            
+            int mappingColumn = model.getComponentMappingIndex();
+            
             try {
+                CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:3879");
+                CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326");
+                MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
                 
-                
-                CoordinateReferenceSystem crs = CRS.decode(null);
-            } catch (FactoryException e) {
-                // TODO Auto-generated catch block
+                Simantics.getSession().syncRequest(new Write() {
+                    
+                    @Override
+                    public void perform(WriteGraph graph) throws DatabaseException {
+                        for (int k = 1; k < rows.size(); k++) {
+                            CSVRecord row = rows.get(k);
+                            
+                            String mappingValue = row.get(mappingColumn);
+
+                            try {
+                                if (model.isVertexImport()) {
+                                    String xCoords = row.get(xCoordColumnIndex);
+                                    String yCoords = row.get(yCoordColumnIndex);
+                                    double xCoord = Double.parseDouble(xCoords);
+                                    double yCoord = Double.parseDouble(yCoords);
+                                    
+                                    String zs = row.get(zCoordColumnIndex);
+                                    double z = Double.parseDouble(zs);
+                                    
+                                    DirectPosition2D targetPos = new DirectPosition2D();
+                                    DirectPosition2D sourcePos = new DirectPosition2D(xCoord, yCoord);
+                                    DirectPosition res = transform.transform(sourcePos, targetPos);
+                                    double[] coords = res.getCoordinate();
+                                    Resource vertex = DistrictNetworkUtil.createVertex(graph, model.getParentDiagram(), new double[] { coords[1], -coords[0]}, model.getComponentMappings().get(mappingValue));
+                                    graph.claimLiteral(vertex, DistrictNetworkResource.getInstance(graph).Vertex_HasElevation, z, Bindings.DOUBLE);
+                                } else {
+                                    String startXCoords = row.get(startXCoordColumnIndex);
+                                    String startYCoords = row.get(startYCoordColumnIndex);
+                                    String endXCoords = row.get(endXCoordColumnIndex);
+                                    String endYCoords = row.get(endYCoordColumnIndex);
+                                    
+                                    double startXCoord = Double.parseDouble(startXCoords);
+                                    double startYCoord = Double.parseDouble(startYCoords);
+                                    
+                                    double endXCoord = Double.parseDouble(endXCoords);
+                                    double endYCoord = Double.parseDouble(endYCoords);
+                                    
+                                    DirectPosition2D startTargetPos = new DirectPosition2D();
+                                    DirectPosition2D startSourcePos = new DirectPosition2D(startXCoord, startYCoord);
+                                    DirectPosition startRes = transform.transform(startSourcePos, startTargetPos);
+                                    double[] startCoords = startRes.getCoordinate();
+                                    
+                                    DirectPosition2D endTargetPos = new DirectPosition2D();
+                                    DirectPosition2D endSourcePos = new DirectPosition2D(endXCoord, endYCoord);
+                                    DirectPosition endRes = transform.transform(endSourcePos, endTargetPos);
+                                    double[] endCoords = endRes.getCoordinate();
+                                    
+                                    Resource edge = DNEdgeBuilder.create(graph, model.getParentDiagram(), new double[] { startCoords[1], -startCoords[0]}, new double[] { endCoords[1], -endCoords[0]}, 0.0000001);
+                                    graph.claim(edge, DistrictNetworkResource.getInstance(graph).HasMapping, model.getComponentMappings().get(mappingValue));
+//                                    graph.claimLiteral(edge, DistrictNetworkResource.getInstance(graph).Edge_HasDiameter, value);
+                                }
+                            } catch (MismatchedDimensionException | TransformException | DatabaseException e) {
+                                e.printStackTrace();
+                            }
+                            
+                        }
+                    }
+                });
+                return true;
+            } catch (FactoryException | DatabaseException e) {
                 e.printStackTrace();
             }
             
-            
-            DistrictImportUtils.importCSVAsLayer(csvFile);
         } catch (IOException e) {
             e.printStackTrace();
         }
diff --git a/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizardFirstPage.java b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizardFirstPage.java
new file mode 100644 (file)
index 0000000..830b126
--- /dev/null
@@ -0,0 +1,125 @@
+package org.simantics.district.imports.ui;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.district.network.ui.function.Functions;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.utils.ui.widgets.FileOrDirectorySelectionWidget;
+import org.simantics.utils.ui.widgets.FileSelectionListener;
+import org.simantics.utils.ui.widgets.FileSelectionWidget;
+
+public class CSVImportWizardFirstPage extends WizardPage implements FileSelectionListener {
+
+    private final CSVImportModel model;
+    
+    private Map<String, Resource> diagrams = new HashMap<>();
+    
+    private Combo diagramCombo;
+    private FileSelectionWidget csvSelection;
+
+    public CSVImportWizardFirstPage(CSVImportModel model) {
+        super("Select source for CSV data");
+        this.model = model;
+        setMessage("Select target network diagram and source for CSV-data");
+    }
+    
+    @Override
+    public void createControl(Composite parent) {
+        Composite composite = new Composite(parent, SWT.NONE);
+        composite.setLayout(new GridLayout(1,false));
+        GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(composite);
+        
+        Group parentConfigurationGroup = new Group(composite, SWT.NONE);
+        parentConfigurationGroup.setText("Select target network diagram");
+        GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(parentConfigurationGroup);
+        
+        diagramCombo = new Combo(parentConfigurationGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
+        diagramCombo.addSelectionListener(new SelectionListener() {
+            
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                widgetDefaultSelected(e);
+            }
+            
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                String selection = diagramCombo.getItem(diagramCombo.getSelectionIndex());
+                model.setParentDiagram(diagrams.get(selection));
+                validateComplete();
+            }
+        });
+        
+        GridLayoutFactory.fillDefaults().numColumns(1).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(parentConfigurationGroup);
+        
+        csvSelection = new FileSelectionWidget(composite, "CSV file", SWT.OPEN);
+        csvSelection.addListener(this);
+        
+        updateAvailableParents();
+        
+        validateComplete();
+        
+        setControl(composite);
+    }
+
+    private void updateAvailableParents() {
+        try {
+            Simantics.getSession().syncRequest(new ReadRequest() {
+                
+                @Override
+                public void run(ReadGraph graph) throws DatabaseException {
+                    Collection<Resource> diagrams = Functions.getDistrictDiagrams(graph);
+                    ModelingResources MOD = ModelingResources.getInstance(graph);
+                    Resource projectResource = Simantics.getProjectResource();
+                    String projectURI = graph.getURI(projectResource);
+                    for (Resource diagram : diagrams) {
+                        Resource composite = graph.getSingleObject(diagram, MOD.DiagramToComposite);
+                        String compositeURI = graph.getURI(composite);
+                        String path = compositeURI.replace(projectURI, "");
+                        CSVImportWizardFirstPage.this.diagrams.put(path, diagram);
+                    }
+                }
+            });
+            diagramCombo.setItems(diagrams.keySet().toArray(new String[diagrams.size()]));
+        } catch (DatabaseException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void fileSelected(FileOrDirectorySelectionWidget source, String[] filename) {
+        String[] selection = csvSelection.getFilename();
+        if (selection != null && selection.length > 0) {
+            Path csvFile = Paths.get(selection[0]);
+            if (!Files.exists(csvFile)) {
+                setErrorMessage("File " + csvFile.toAbsolutePath() + " does not exist");
+            } else {
+                model.setSource(csvFile);
+                validateComplete();
+            }
+        }
+    }
+    
+    private void validateComplete() {
+        setPageComplete(model.getSource() != null && model.getParentDiagram() != null);
+    }
+}
index e4a0612a2358e8b4a6a609d6146cb45ea084f504..9d1d08c422c1627480beb0ae1a71ee4117509b68 100644 (file)
@@ -4,13 +4,19 @@ import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.commons.csv.CSVRecord;
+import org.eclipse.jface.dialogs.IPageChangeProvider;
+import org.eclipse.jface.dialogs.IPageChangedListener;
+import org.eclipse.jface.dialogs.PageChangedEvent;
 import org.eclipse.jface.layout.GridDataFactory;
 import org.eclipse.jface.layout.TableColumnLayout;
 import org.eclipse.jface.viewers.ColumnWeightData;
-import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.wizard.IWizardContainer;
 import org.eclipse.jface.wizard.WizardPage;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionEvent;
@@ -19,144 +25,371 @@ import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
 import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.swt.widgets.TableItem;
-import org.simantics.district.network.ui.function.Functions;
+import org.simantics.district.imports.ui.controls.DynamicComboFieldEditor;
 import org.simantics.utils.ui.widgets.FileOrDirectorySelectionWidget;
 import org.simantics.utils.ui.widgets.FileSelectionListener;
 import org.simantics.utils.ui.widgets.FileSelectionWidget;
 
-
-public class CSVImportWizardPage extends WizardPage implements FileSelectionListener {
+public class CSVImportWizardPage extends WizardPage {
 
     private CSVImportModel model;
-    private FileSelectionWidget csvSelection;
+
+    private Map<Integer, String> headerIndexAndValues = new HashMap<>();
+
     private Table headerTable;
     private Button firstAsHeader;
-    
-    private Combo diagramCombo;
-    
-    
+
     private Combo delimiterCombo;
-    private Combo delimiterdCombo;
     private TableColumnLayout tableColumnLayout;
-    private TableViewer tableViewer;
     private Composite tableComposite;
     private FileSelectionWidget wktFileSelection;
+
+    // Common for vertex and edge
+    private DynamicComboFieldEditor componentMappingSelector;
+    private DynamicComboFieldEditor labelSelector;
     
-    private Path wktFile;
+    // For vertex import
+    private DynamicComboFieldEditor xCoordSelector;
+    private DynamicComboFieldEditor yCoordSelector;
+    private DynamicComboFieldEditor zValueSelector;
+
+    // For edge import
+    private DynamicComboFieldEditor startXCoordSelector;
+    private DynamicComboFieldEditor startYCoordSelector;
+    private DynamicComboFieldEditor startZValueSelector;
+    private DynamicComboFieldEditor endXCoordSelector;
+    private DynamicComboFieldEditor endYCoordSelector;
+    private DynamicComboFieldEditor endZValueSelector;
+
+    private Group indexMappingGroup;
+
+    private Composite composite;
 
+    private Button isVertexImport;
+    
     protected CSVImportWizardPage(CSVImportModel model) {
         super("Import CSV Data");
         this.model = model;
-        setMessage("Select CSV file to import");
+        setMessage("Select columng index mappings");
     }
 
     @Override
     public void createControl(Composite parent) {
-        Composite composite = new Composite(parent, SWT.NONE);
-        composite.setLayout(new GridLayout(1,false));
+        composite = new Composite(parent, SWT.NONE);
+        composite.setLayout(new GridLayout(1, false));
         GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(composite);
-        
-        diagramCombo = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
-        diagramCombo.setItems(getDistrictDiagrams());
-        
-        
-        csvSelection = new FileSelectionWidget(composite, "CSV file", SWT.OPEN);
-        csvSelection.addListener(this);
-        
+
         delimiterCombo = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
         delimiterCombo.setItems(model.getDelimiterFormats());
         delimiterCombo.addSelectionListener(new SelectionListener() {
-            
+
             @Override
             public void widgetSelected(SelectionEvent e) {
                 model.setDelimiterByLabel(delimiterCombo.getItem(delimiterCombo.getSelectionIndex()));
                 updateHeaders();
+                updateCombos();
             }
-            
+
             @Override
             public void widgetDefaultSelected(SelectionEvent e) {
-                
+                widgetSelected(e);
             }
         });
-        
+
         firstAsHeader = new Button(composite, SWT.CHECK);
         firstAsHeader.setText("Read first row as header");
         firstAsHeader.setSelection(model.getReadFirstAsHeader());
         firstAsHeader.addSelectionListener(new SelectionListener() {
-            
+
             @Override
             public void widgetSelected(SelectionEvent e) {
                 model.setReadFirstAsHeader(firstAsHeader.getSelection());
                 updateHeaders();
+                updateCombos();
             }
-            
+
             @Override
             public void widgetDefaultSelected(SelectionEvent e) {
-                
+
             }
         });
-        
-        
+
         tableComposite = new Composite(composite, SWT.BORDER);
         tableColumnLayout = new TableColumnLayout();
         tableComposite.setLayout(tableColumnLayout);
 
-        
-        
         wktFileSelection = new FileSelectionWidget(composite, "WKT file", SWT.OPEN);
         wktFileSelection.addListener(new FileSelectionListener() {
-            
+
             @Override
             public void fileSelected(FileOrDirectorySelectionWidget source, String[] filename) {
                 String[] selection = wktFileSelection.getFilename();
                 if (selection != null && selection.length > 0) {
-                    Path wktFilee = Paths.get(selection[0]);
-                    if (!Files.exists(wktFilee)) {
-                        setErrorMessage("File " + wktFilee.toAbsolutePath() + " does not exist");
+                    Path wktFile = Paths.get(selection[0]);
+                    if (!Files.exists(wktFile)) {
+                        setErrorMessage("File " + wktFile.toAbsolutePath() + " does not exist");
                     } else {
-                        wktFile = wktFilee;
-                        setPageComplete(true);
+                        model.setWKTFile(wktFile);
+                        validatePageComplete();
                     }
-                } else {
-                    setPageComplete(false);
-                } 
+                }
+            }
+        });
+
+        isVertexImport = new Button(composite, SWT.CHECK);
+        isVertexImport.setText("File contains vertices");
+        isVertexImport.setSelection(model.isVertexImport());
+        isVertexImport.addSelectionListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                model.setVertexImport(isVertexImport.getSelection());
+                updateControls(false);
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                widgetSelected(e);
             }
         });
         
+        updateControls(true);
         updateHeaders();
+        setControl(composite);
+
+        final IWizardContainer container = getContainer();
         
+        if (container instanceof IPageChangeProvider) {
+            ((IPageChangeProvider) container).addPageChangedListener(new IPageChangedListener() {
+
+                @Override
+                public void pageChanged(PageChangedEvent event) {
+                    if (isCurrentPage())
+                        CSVImportWizardPage.this.updateControls(false);
+                }
+            });
+        }
+
+        validatePageComplete();
+    }
+    
+    private void updateControls(boolean initial) {
+        createIndexMappingGroup();
+        updateCombos();
+        if (!initial)
+            composite.layout(true, true);
+    }
+    
+    private void createIndexMappingGroup() {
+        if (indexMappingGroup != null)
+            indexMappingGroup.dispose();
         
+        indexMappingGroup = new Group(composite, SWT.NONE);
+        indexMappingGroup.setText("Column index mapping");
+        GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(indexMappingGroup);
         
-        setControl(composite);
+        if (model.isVertexImport())
+            createVertexIndexMappingField(indexMappingGroup);
+        else
+            createEdgeIndexMappingField(indexMappingGroup);
         
+        createCommonIndexMappingField(indexMappingGroup);
+    }
+
+    private void createCommonIndexMappingField(Group parent) {
         
+        componentMappingSelector = new DynamicComboFieldEditor("componentMapping", "Apros component mapping", parent);
+        componentMappingSelector.addComboListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                widgetDefaultSelected(e);
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                model.setComponentMappingIndex(Integer.parseInt(componentMappingSelector.getValue()));
+                validatePageComplete();
+            }
+        });
         
-        setPageComplete(false);
     }
 
-    private String[] getDistrictDiagrams() {
-        Functions.getDistrictDiagrams(null);
-        return null;
+    private void createVertexIndexMappingField(Group parent) {
+        xCoordSelector = new DynamicComboFieldEditor("xCoord", "X Coordinate", parent);
+        xCoordSelector.addComboListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                widgetDefaultSelected(e);
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                model.setXCoordIndex(Integer.parseInt(xCoordSelector.getValue()));
+                validatePageComplete();
+            }
+        });
+
+        yCoordSelector = new DynamicComboFieldEditor("yCoord", "Y Coordinate", parent);
+        yCoordSelector.addComboListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                widgetDefaultSelected(e);
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                model.setYCoordIndex(Integer.parseInt(yCoordSelector.getValue()));
+                validatePageComplete();
+            }
+        });
+        zValueSelector = new DynamicComboFieldEditor("zValue", "Z Value", parent);
+        zValueSelector.addComboListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                widgetDefaultSelected(e);
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                model.setZCoordIndex(Integer.parseInt(zValueSelector.getValue()));
+                validatePageComplete();
+            }
+        });
     }
 
-    @Override
-    public void fileSelected(FileOrDirectorySelectionWidget source, String[] filename) {
-        String[] selection = csvSelection.getFilename();
-        if (selection != null && selection.length > 0) {
-            Path csvFile = Paths.get(selection[0]);
-            if (!Files.exists(csvFile)) {
-                setErrorMessage("File " + csvFile.toAbsolutePath() + " does not exist");
-            } else {
-                model.setSource(csvFile);
-                updateHeaders();
-                setPageComplete(true);
+    private void createEdgeIndexMappingField(Group parent) {
+        startXCoordSelector = new DynamicComboFieldEditor("startxCoord", "Start X Coordinate", parent);
+        startXCoordSelector.addComboListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                widgetDefaultSelected(e);
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                model.setStartXCoordIndex(Integer.parseInt(startXCoordSelector.getValue()));
+                validatePageComplete();
+            }
+        });
+
+        startYCoordSelector = new DynamicComboFieldEditor("startyCoord", "Start Y Coordinate", parent);
+        startYCoordSelector.addComboListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                widgetDefaultSelected(e);
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                model.setStartYCoordIndex(Integer.parseInt(startYCoordSelector.getValue()));
+                validatePageComplete();
+            }
+        });
+        startZValueSelector = new DynamicComboFieldEditor("startzValue", "Start Z Value", parent);
+        startZValueSelector.addComboListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                widgetDefaultSelected(e);
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                model.setStartZCoordIndex(Integer.parseInt(startZValueSelector.getValue()));
+                validatePageComplete();
+            }
+        });
+        
+        endXCoordSelector = new DynamicComboFieldEditor("endxCoord", "End X Coordinate", parent);
+        endXCoordSelector.addComboListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                widgetDefaultSelected(e);
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                model.setEndXCoordIndex(Integer.parseInt(endXCoordSelector.getValue()));
+                validatePageComplete();
+            }
+        });
+
+        endYCoordSelector = new DynamicComboFieldEditor("endyCoord", "End Y Coordinate", parent);
+        endYCoordSelector.addComboListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                widgetDefaultSelected(e);
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                model.setEndYCoordIndex(Integer.parseInt(endYCoordSelector.getValue()));
+                validatePageComplete();
+            }
+        });
+        endZValueSelector = new DynamicComboFieldEditor("endzValue", "End Z Value", parent);
+        endZValueSelector.addComboListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                widgetDefaultSelected(e);
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                model.setEndZCoordIndex(Integer.parseInt(endZValueSelector.getValue()));
+                validatePageComplete();
             }
-        } else {
-            setPageComplete(false);
+        });
+    }
+
+    private void updateCombos() {
+        String[][] namesAndValues = new String[headerIndexAndValues.size()][];
+
+        int i = 0;
+        for (Entry<Integer, String> entry : headerIndexAndValues.entrySet()) {
+            int key = entry.getKey();
+            String value = entry.getValue();
+
+            String[] nameAndValue = new String[2];
+            nameAndValue[0] = value;
+            nameAndValue[1] = Integer.toString(key);
+            namesAndValues[i++] = nameAndValue;
         }
+
+        if (model.isVertexImport())
+            updateVertexcombos(namesAndValues);
+        else
+            updateEdgeCombos(namesAndValues);
+
+        componentMappingSelector.updateCombo(namesAndValues);
+    }
+
+    private void updateEdgeCombos(String[][] namesAndValues) {
+        startXCoordSelector.updateCombo(namesAndValues);
+        endXCoordSelector.updateCombo(namesAndValues);
+        startYCoordSelector.updateCombo(namesAndValues);
+        endYCoordSelector.updateCombo(namesAndValues);
+        startZValueSelector.updateCombo(namesAndValues);
+        endZValueSelector.updateCombo(namesAndValues);
+    }
+
+    private void updateVertexcombos(String[][] namesAndValues) {
+        xCoordSelector.updateCombo(namesAndValues);
+        yCoordSelector.updateCombo(namesAndValues);
+        zValueSelector.updateCombo(namesAndValues);
     }
 
     private void updateHeaders() {
@@ -174,21 +407,26 @@ public class CSVImportWizardPage extends WizardPage implements FileSelectionList
             TableItem item = headerTable.getItem(i);
             item.dispose();
         }
+
+        headerIndexAndValues.clear();
+
         try {
             List<CSVRecord> rows = model.getRows(5);
-            
+
             for (int k = 0; k < rows.size(); k++) {
                 CSVRecord row = rows.get(k);
-                
+
                 int columnCount = row.size();
                 for (int i = 0; i < columnCount; i++) {
                     String value = row.get(i);
                     if (k == 0) {
                         TableColumn headerCol = new TableColumn(headerTable, SWT.NONE);
                         headerCol.setText(value);
-                        
+
                         tableColumnLayout.setColumnData(headerCol, new ColumnWeightData(10));
                         headerCol.pack();
+
+                        headerIndexAndValues.put(i, value);
                     } else {
                         int actualK = k - 1;
                         TableItem item;
@@ -202,29 +440,17 @@ public class CSVImportWizardPage extends WizardPage implements FileSelectionList
                     }
                 }
             }
-            
-//            Map<CSVHeader, List<String>> headerAndValues = model.getHeaderAndRows(5);
-//            
-//            int coo = headerTable.getColumns().length;
-//            int count = headerTable.getColumnCount();
-//            
-//            for (Map.Entry<CSVHeader, List<String>> entr : headerAndValues.entrySet()) {
-//                CSVHeader he = entr.getKey();
-//                int index = he.getIndex();
-//                TableColumn headerCol = new TableColumn(headerTable, SWT.NONE);
-//                headerCol.setText(he.getHeader());
-//                
-//                tableColumnLayout.setColumnData(headerCol, new ColumnWeightData(10));
-//                headerCol.pack();
-//                
-//                for (String val : entr.getValue()) {
-//                    TableItem item = new TableItem(headerTable, SWT.NONE);
-//                    item.setText(val);
-//                }
-//            }
+
         } catch (IOException e) {
             setErrorMessage(e.getMessage());
         }
     }
 
+    protected void validatePageComplete() {
+        if (model.isVertexImport())
+            setPageComplete(model.getXCoordIndex() != -1 && model.getYCoordIndex() != -1 && model.getComponentMappingIndex() != -1);
+        else
+            setPageComplete(model.getStartXCoordIndex() != 1 && model.getStartYCoordIndex() != -1 && model.getEndXCoordIndex() != -1 && model.getEndYCoordIndex() != -1 && model.getComponentMappingIndex() != -1);
+    }
+
 }
diff --git a/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/ComponentMappingPage.java b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/ComponentMappingPage.java
new file mode 100644 (file)
index 0000000..5cf5551
--- /dev/null
@@ -0,0 +1,133 @@
+package org.simantics.district.imports.ui;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+import org.eclipse.jface.dialogs.IPageChangeProvider;
+import org.eclipse.jface.dialogs.IPageChangedListener;
+import org.eclipse.jface.dialogs.PageChangedEvent;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.wizard.IWizardContainer;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.district.imports.DistrictImportUtils;
+import org.simantics.district.network.ui.function.Functions;
+
+public class ComponentMappingPage extends WizardPage {
+    
+    private CSVImportModel model;
+    private Composite composite;
+    private Composite childComposite;
+    protected Map<String, Resource> componentMappings;
+    private Collection<String> distinctMappingIvalues;
+    private Collection<String> distinctMappingIndexColumnValues;
+
+    public ComponentMappingPage(CSVImportModel model) {
+        super("Select component mappings");
+        this.model = model;
+        setMessage("Select component mappings");
+    }
+
+    @Override
+    public void createControl(Composite parent) {
+        composite = new Composite(parent, SWT.NONE);
+        composite.setLayout(new GridLayout(1,false));
+        GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(composite);
+        
+        setControl(composite);
+        
+        validatePageComplete();
+        
+        IWizardContainer container = getContainer();
+        if (container instanceof IPageChangeProvider) {
+            ((IPageChangeProvider) container).addPageChangedListener(new IPageChangedListener() {
+
+                @Override
+                public void pageChanged(PageChangedEvent event) {
+                    if (container.getCurrentPage().equals(ComponentMappingPage.this)) {
+                        ComponentMappingPage.this.updateComponentMappings();
+                    }
+                }
+            });
+        }
+    }
+    
+    private void updateComponentMappings() {
+        try {
+            int mappingIndex = model.getComponentMappingIndex();
+            distinctMappingIndexColumnValues = DistrictImportUtils.readDistinctValuesOfColumn(model.getSource(), model.getDelimiter(), mappingIndex);
+            
+            try {
+                Simantics.getSession().sync(new ReadRequest() {
+                    
+                    @Override
+                    public void run(ReadGraph graph) throws DatabaseException {
+                        if (model.isVertexImport())
+                            componentMappings = Functions.getVertexMappings(graph, model.getParentDiagram());
+                        else
+                            componentMappings = Functions.getEdgeMappings(graph, model.getParentDiagram());
+                    }
+                });
+            } catch (DatabaseException e) {
+                e.printStackTrace();
+            }
+            
+            System.out.println(distinctMappingIndexColumnValues);
+            if (childComposite != null)
+                childComposite.dispose();
+            childComposite = new Composite(composite, SWT.NONE);
+            childComposite.setLayout(new GridLayout(1,false));
+            GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(childComposite);
+            
+            for (String value : distinctMappingIndexColumnValues) {
+                
+                Composite newCompo = new Composite(childComposite, SWT.NONE);
+                newCompo.setLayout(new GridLayout(2,false));
+                GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(newCompo);
+                
+                Label t = new Label(newCompo, SWT.NONE);
+                t.setText(value);
+                
+                Combo c = new Combo(newCompo, SWT.READ_ONLY);
+                c.setItems(componentMappings.keySet().toArray(new String[componentMappings.size()]));
+                c.addSelectionListener(new SelectionListener() {
+                    
+                    @Override
+                    public void widgetSelected(SelectionEvent e) {
+                        model.setComponentMappings(value, componentMappings.get(c.getItem(c.getSelectionIndex())));
+                        validatePageComplete();
+                    }
+                    
+                    @Override
+                    public void widgetDefaultSelected(SelectionEvent e) {
+                        widgetSelected(e);
+                    }
+                });
+            }
+            composite.layout(true, true);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void validatePageComplete() {
+        Map<String, Resource> currentMappings = model.getComponentMappings();
+        if (currentMappings != null && distinctMappingIndexColumnValues != null && currentMappings.keySet().containsAll(distinctMappingIndexColumnValues))
+            setPageComplete(true);
+        else 
+            setPageComplete(false);
+    }
+
+}
diff --git a/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/controls/DynamicComboFieldEditor.java b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/controls/DynamicComboFieldEditor.java
new file mode 100644 (file)
index 0000000..5fc8cad
--- /dev/null
@@ -0,0 +1,218 @@
+package org.simantics.district.imports.ui.controls;
+
+import org.eclipse.jface.preference.FieldEditor;
+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.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * A field editor for a combo box that allows the drop-down selection of one of
+ * a list of items.
+ *
+ * @since 3.3
+ */
+public class DynamicComboFieldEditor extends FieldEditor {
+
+       /**
+        * The <code>Combo</code> widget.
+        */
+       private Combo fCombo;
+
+       /**
+        * The value (not the name) of the currently selected item in the Combo widget.
+        */
+       private String fValue;
+
+       /**
+        * The names (labels) and underlying values to populate the combo widget.  These should be
+        * arranged as: { {name1, value1}, {name2, value2}, ...}
+        */
+       private String[][] fEntryNamesAndValues;
+
+       /**
+        * Create the combo box field editor.
+        *
+     * @param name the name of the preference this field editor works on
+     * @param labelText the label text of the field editor
+        * @param entryNamesAndValues the names (labels) and underlying values to populate the combo widget.  These should be
+        * arranged as: { {name1, value1}, {name2, value2}, ...}
+        * @param parent the parent composite
+        */
+       
+       public DynamicComboFieldEditor(String name, String labelText, Composite parent) {
+           init(name, labelText);
+           createControl(parent);
+       }
+       
+       public DynamicComboFieldEditor(String name, String labelText, String[][] entryNamesAndValues, Composite parent) {
+               init(name, labelText);
+               fEntryNamesAndValues = entryNamesAndValues;
+               createControl(parent);
+       }
+       
+       public void updateCombo(String[][] fEntryNamesAndValues) {
+           this.fEntryNamesAndValues = fEntryNamesAndValues;
+           updateComboBoxControl();
+       }
+
+       /**
+        * Checks whether given <code>String[][]</code> is of "type"
+        * <code>String[][2]</code>.
+        *
+        * @return <code>true</code> if it is ok, and <code>false</code> otherwise
+        */
+       private boolean checkArray(String[][] table) {
+               if (table == null) {
+                       return false;
+               }
+               for (int i = 0; i < table.length; i++) {
+                       String[] array = table[i];
+                       if (array == null || array.length != 2) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+
+       @Override
+       protected void adjustForNumColumns(int numColumns) {
+               if (numColumns > 1) {
+                       Control control = getLabelControl();
+                       int left = numColumns;
+                       if (control != null) {
+                               ((GridData)control.getLayoutData()).horizontalSpan = 1;
+                               left = left - 1;
+                       }
+                       ((GridData)fCombo.getLayoutData()).horizontalSpan = left;
+               } else {
+                       Control control = getLabelControl();
+                       if (control != null) {
+                               ((GridData)control.getLayoutData()).horizontalSpan = 1;
+                       }
+                       ((GridData)fCombo.getLayoutData()).horizontalSpan = 1;
+               }
+       }
+
+       @Override
+       protected void doFillIntoGrid(Composite parent, int numColumns) {
+               int comboC = 1;
+               if (numColumns > 1) {
+                       comboC = numColumns - 1;
+               }
+               Control control = getLabelControl(parent);
+               GridData gd = new GridData();
+               gd.horizontalSpan = 1;
+               control.setLayoutData(gd);
+               control = getComboBoxControl(parent);
+               gd = new GridData();
+               gd.horizontalSpan = comboC;
+               gd.horizontalAlignment = GridData.FILL;
+               control.setLayoutData(gd);
+               control.setFont(parent.getFont());
+       }
+
+       @Override
+       protected void doLoad() {
+               updateComboForValue(getPreferenceStore().getString(getPreferenceName()));
+       }
+
+       @Override
+       protected void doLoadDefault() {
+               updateComboForValue(getPreferenceStore().getDefaultString(getPreferenceName()));
+       }
+
+       @Override
+       protected void doStore() {
+               if (fValue == null) {
+                       getPreferenceStore().setToDefault(getPreferenceName());
+                       return;
+               }
+               getPreferenceStore().setValue(getPreferenceName(), fValue);
+       }
+
+       @Override
+       public int getNumberOfControls() {
+               return 2;
+       }
+
+       /*
+        * Lazily create and return the Combo control.
+        */
+       private Combo getComboBoxControl(Composite parent) {
+               if (fCombo == null) {
+            fCombo = new Combo(parent, SWT.READ_ONLY);
+            fCombo.setFont(parent.getFont());
+
+            fCombo.addSelectionListener(new SelectionAdapter() {
+                @Override
+                public void widgetSelected(SelectionEvent evt) {
+                    String oldValue = fValue;
+                    String name = fCombo.getText();
+                    fValue = getValueForName(name);
+                    setPresentsDefaultValue(false);
+                    fireValueChanged(VALUE, oldValue, fValue);
+                }
+            });
+               }
+               updateComboBoxControl();
+               return fCombo;
+       }
+       
+       private void updateComboBoxControl() {
+           fCombo.removeAll();
+           if (fEntryNamesAndValues != null) {
+            for (int i = 0; i < fEntryNamesAndValues.length; i++) {
+                fCombo.add(fEntryNamesAndValues[i][0], i);
+            }
+           }
+       }
+
+       /*
+        * Given the name (label) of an entry, return the corresponding value.
+        */
+       private String getValueForName(String name) {
+               for (int i = 0; i < fEntryNamesAndValues.length; i++) {
+                       String[] entry = fEntryNamesAndValues[i];
+                       if (name.equals(entry[0])) {
+                               return entry[1];
+                       }
+               }
+               return fEntryNamesAndValues[0][0];
+       }
+
+       /*
+        * Set the name in the combo widget to match the specified value.
+        */
+       private void updateComboForValue(String value) {
+               fValue = value;
+               for (int i = 0; i < fEntryNamesAndValues.length; i++) {
+                       if (value.equals(fEntryNamesAndValues[i][1])) {
+                               fCombo.setText(fEntryNamesAndValues[i][0]);
+                               return;
+                       }
+               }
+               if (fEntryNamesAndValues.length > 0) {
+                       fValue = fEntryNamesAndValues[0][1];
+                       fCombo.setText(fEntryNamesAndValues[0][0]);
+               }
+       }
+
+       @Override
+       public void setEnabled(boolean enabled, Composite parent) {
+               super.setEnabled(enabled, parent);
+               getComboBoxControl(parent).setEnabled(enabled);
+       }
+
+    public void addComboListener(SelectionListener selectionListener) {
+        fCombo.addSelectionListener(selectionListener);
+    }
+    
+    public String getValue() {
+        return fValue;
+    }
+}
index 1ad5b9a9487c0667d91a553cd6ecc461b1851156..100c307e35d67e46e5296038eb05b26a786b2e7f 100644 (file)
@@ -4,10 +4,13 @@ import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.csv.CSVFormat;
 import org.apache.commons.csv.CSVParser;
@@ -17,8 +20,7 @@ import org.simantics.db.Resource;
 public class DistrictImportUtils {
 
     private DistrictImportUtils() { }
-    
-    
+
     public static Resource importCSVAsLayer(Path csvFile) throws IOException {
         
         try (CSVParser parser = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(Files.newBufferedReader(csvFile))) {
@@ -172,4 +174,20 @@ public class DistrictImportUtils {
         }
     }
 
+    public static Collection<String> readDistinctValuesOfColumn(Path source, char delim, int mappingIndex) throws IOException {
+        Set<String> results = new HashSet<>();
+        CSVFormat format = CSVFormat.newFormat(delim);
+        try (CSVParser parser = format.parse(Files.newBufferedReader(source))) {
+            Iterator<CSVRecord> records = parser.iterator();
+            if (records.hasNext())
+                records.next();
+            while (records.hasNext()) {
+                CSVRecord row = records.next();
+                String value = row.get(mappingIndex);
+                results.add(value);
+            }
+        }
+        return results;
+    }
+
 }
diff --git a/org.simantics.district.maps/src/org/simantics/maps/MapScalingTransform.java b/org.simantics.district.maps/src/org/simantics/maps/MapScalingTransform.java
new file mode 100644 (file)
index 0000000..e208be7
--- /dev/null
@@ -0,0 +1,19 @@
+package org.simantics.maps;
+
+import java.awt.geom.AffineTransform;
+
+public class MapScalingTransform {
+
+    private MapScalingTransform() {
+    }
+
+    public static final AffineTransform INSTANCE = new AffineTransform(100000, 0, 0, 100000, 0, 0);
+
+    public static double getScaleX() {
+        return INSTANCE.getScaleX();
+    }
+
+    public static double getScaleY() {
+        return INSTANCE.getScaleY();
+    }
+}
index e06adcb27e2d82ef8757cc9e4a8e96c6738313fc..b8b54e31afa380b30c28a9e773d1122e9fff5d21 100644 (file)
@@ -224,9 +224,8 @@ public class MapNode extends G2DNode implements ITileListener  {
             return;
 
         Graphics2D g = (Graphics2D)g2d.create();
-
         AffineTransform tr = (AffineTransform)g.getTransform().clone();
-
+        
         double scaleX = Math.abs(tr.getScaleX());
         double scaleY = Math.abs(tr.getScaleY());
         if (scaleX <= 0 || scaleY <= 0) {
@@ -255,7 +254,7 @@ public class MapNode extends G2DNode implements ITileListener  {
             tileSize *= 0.5;
             level++;
         }
-
+        System.out.println("level " + level);
         /*
          *  To convert y-coordinates to map coordinates in ruler, use:
          *    double val = (y-offsetY)/scaleY;
index a8b273c2bbd091c31327bd5e5e903aff3a130594..2815e2f3f9098a21d7acc6cade172ca3768bb810 100644 (file)
Binary files a/org.simantics.district.network.ui.ontology/graph.tg and b/org.simantics.district.network.ui.ontology/graph.tg differ
index c03c89c5771a16be1d6c9036389da1ec8bfd7f68..26d246fbf092044a20e6c66bdc42e4ebd05c6901 100644 (file)
@@ -10,12 +10,12 @@ DNUI = <http://www.simantics.org/DistrictNetworkUI-1.0> : L0.Ontology
     L0.Ontology.global true
     L0.HasResourceClass "org.simantics.district.network.ui.ontology.DistrictNetworkUIResource"
 
-DNUI.SelectionTabContribution : SEL.MultiTypedVariableTabContribution
-    SEL.TypedTabContribution.HasType DN.Vertex
-    SEL.TypedTabContribution.HasType DN.Edge
-    SEL.TypedTabContribution.HasType DN.Diagram
+DNUI.SelectionTabContribution : SEL.TypedVariableTabContribution
+    SEL.TypedVariableTabContribution.HasType DN.Vertex
+    SEL.TypedVariableTabContribution.HasType DN.Edge
+    SEL.TypedVariableTabContribution.HasType DN.Diagram
     SEL.VariableTabContribution.HasView SEL_UI.StandardProperties
-    SEL.TabContribution.HasPriority 10
+    SEL.VariableTabContribution.HasPriority 10
     L0.HasLabel "Network Properties"
 
 DNUI.NetworkProperties : SEL_UI.StandardProperties
index b3aef5400f3e93c72ade1f550d8988eb79e96743..8db22872e7e7d39d6097d9d345fe1a17a01f4643 100644 (file)
@@ -4,7 +4,8 @@ Bundle-Name: Simantics District Network UI
 Bundle-SymbolicName: org.simantics.district.network.ui;singleton:=true
 Bundle-Version: 1.0.0.qualifier
 Bundle-Activator: org.simantics.district.network.ui.internal.Activator
-Export-Package: org.simantics.district.network.ui.adapters,
+Export-Package: org.simantics.district.network.ui,
+ org.simantics.district.network.ui.adapters,
  org.simantics.district.network.ui.function
 Require-Bundle: org.eclipse.e4.ui.model.workbench;bundle-version="1.1.100.v20150407-1430",
  org.eclipse.swt,
index f0c705c81dd7355a2c8f730a5eb5c2c5cc62c894..6271c820f9461fb62235ecd828909484d2c9e79c 100644 (file)
@@ -8,6 +8,7 @@
     <elements xsi:type="commands:Command" xmi:id="_6lrYUML_Eea1mdgpHNVHMA" elementId="org.simantics.district.network.ui.command.openDistrictEditor" commandName="Open District Editor"/>
     <elements xsi:type="commands:Command" xmi:id="_A1HBQOFYEeaJP6VyXP72Jw" elementId="org.simantics.district.network.ui.joinVertices" commandName="Join Vertices"/>
     <elements xsi:type="commands:Command" xmi:id="_QzdUQOIcEeaJP6VyXP72Jw" elementId="org.simantics.district.network.ui.setFocusable" commandName="Set Focusable"/>
+    <elements xsi:type="commands:Command" xmi:id="_4wJtADWxEeeVXaXEq4_qpA" elementId="org.simantics.district.network.ui.command.changemapping" commandName="Change Mapping"/>
   </fragments>
   <fragments xsi:type="fragment:StringModelFragment" xmi:id="_Js7rUMMAEea1mdgpHNVHMA" featurename="menuContributions" parentElementId="xpath:/">
     <elements xsi:type="menu:MenuContribution" xmi:id="_MbrJgMMAEea1mdgpHNVHMA" elementId="org.simantics.district.network.ui.menucontribution.0" parentId="help">
       <children xsi:type="menu:HandledMenuItem" xmi:id="_VCxYIN8NEeaigNyzMJBOrg" elementId="org.simantics.district.network.ui.handledmenuitem.importImage" label="Import PNG/SVG Image" iconURI="platform:/plugin/org.simantics.modeling.ui/icons/image_add.png" tooltip="Import PNG/SVG Image as a layout" command="_luNasN8NEeaigNyzMJBOrg"/>
       <children xsi:type="menu:HandledMenuItem" xmi:id="_O_UgUOIgEeaJP6VyXP72Jw" elementId="org.simantics.district.network.ui.handledmenuitem.joinvertices" label="Join Vertices" iconURI="platform:/plugin/org.simantics.ui/icons/etool16/arrow_join.png" tooltip="Join multiple vertices as one" command="_A1HBQOFYEeaJP6VyXP72Jw"/>
       <children xsi:type="menu:DynamicMenuContribution" xmi:id="_dieAsOIgEeaJP6VyXP72Jw" elementId="org.simantics.district.network.ui.dynamicmenucontribution.setFocusable" label="Set Focusable" contributionURI="bundleclass://org.simantics.district.network.ui/org.simantics.district.network.ui.contributions.SetFocusableDynamicMenuContribution"/>
+      <children xsi:type="menu:HandledMenuItem" xmi:id="_QbF4UDWyEeeVXaXEq4_qpA" elementId="org.simantics.district.network.ui.handledmenuitem.changemapping" label="Change Mapping" tooltip="Change mapping of multiple elements" command="_4wJtADWxEeeVXaXEq4_qpA"/>
     </elements>
   </fragments>
   <fragments xsi:type="fragment:StringModelFragment" xmi:id="_dbiHcMMBEea1mdgpHNVHMA" featurename="handlers" parentElementId="xpath:/">
     <elements xsi:type="commands:Handler" xmi:id="_DPcVsOFYEeaJP6VyXP72Jw" elementId="org.simantics.district.network.ui.handler.joinVertices" contributionURI="bundleclass://org.simantics.district.network.ui/org.simantics.district.network.ui.contributions.JoinVerticesHandler" command="_A1HBQOFYEeaJP6VyXP72Jw"/>
     <elements xsi:type="commands:Handler" xmi:id="_VPgBwOIcEeaJP6VyXP72Jw" elementId="org.simantics.district.network.ui.handler.setFocusable" contributionURI="bundleclass://org.simantics.district.network.ui/org.simantics.district.network.ui.contributions.SetFocusableHandler" command="_QzdUQOIcEeaJP6VyXP72Jw"/>
+    <elements xsi:type="commands:Handler" xmi:id="_LojWYDWyEeeVXaXEq4_qpA" elementId="org.simantics.district.network.ui.handler.0" contributionURI="bundleclass://org.simantics.district.network.ui/org.simantics.district.network.ui.contributions.ChangeMappingTypeHandler" command="_4wJtADWxEeeVXaXEq4_qpA"/>
   </fragments>
 </fragment:ModelFragments>
index ebdb9e87adde5dd422eeedcac5dea37c5fea5d97..eb0814450768ed5de2651dfee24f81c94a0cb108 100644 (file)
@@ -12,9 +12,11 @@ import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.diagram.stubs.DiagramResource;
 import org.simantics.diagram.synchronization.IModifiableSynchronizationContext;
 import org.simantics.diagram.synchronization.SynchronizationHints;
-import org.simantics.diagram.synchronization.graph.AddElement;
+import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
 import org.simantics.diagram.synchronization.graph.GraphSynchronizationHints;
+import org.simantics.diagram.synchronization.graph.layer.GraphLayer;
 import org.simantics.diagram.synchronization.graph.layer.GraphLayerManager;
+import org.simantics.diagram.synchronization.graph.layer.IGraphLayerUtil;
 import org.simantics.district.network.DistrictNetworkUtil;
 import org.simantics.district.network.ontology.DistrictNetworkResource;
 import org.simantics.g2d.diagram.IDiagram;
@@ -34,29 +36,40 @@ public class DNEdgeBuilder {
         glm = context.get(GraphSynchronizationHints.GRAPH_LAYER_MANAGER);
     }
 
-    public void create(WriteGraph graph, double[] start, double[] end, double padding) throws DatabaseException {
+    public static Resource create(WriteGraph graph, Resource diagramResource, double[] start, double[] end, double padding) throws DatabaseException {
         
         DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
         
         // 1. Get diagram edge to construct
-        Resource edge = getOrCreateEdge(graph);
-        
-        // 1.1 Give running name to connection and increment the counter attached to the diagram.
-        AddElement.claimFreshElementName(graph, diagramResource, edge);
+        Resource edge = getOrCreateEdge(graph, diagramResource);
         
         // 2. Add vertices
         Collection<Resource> vertices = graph.syncRequest(new ObjectsWithType(diagramResource, Layer0.getInstance(graph).ConsistsOf, DistrictNetworkResource.getInstance(graph).Vertex));
-        Resource startVertex = getOrCreateVertex(graph, vertices, start, padding);
-        Resource endVertex = getOrCreateVertex(graph, vertices, end, padding);
+        Resource startVertex = getOrCreateVertex(graph, diagramResource, vertices, start, padding);
+        Resource endVertex = getOrCreateVertex(graph, diagramResource, vertices, end, padding);
         
         graph.claim(edge, DN.HasStartVertex, startVertex);
         graph.claim(edge, DN.HasEndVertex, endVertex);
         
+        // We need to put GraphLayer to newLayers so...
+        for (Resource layer : graph.getObjects(diagramResource, DiagramResource.getInstance(graph).HasLayer)) {
+            IGraphLayerUtil layerUtil = graph.adapt(graph.getSingleObject(layer, Layer0.getInstance(graph).InstanceOf), IGraphLayerUtil.class);
+            
+            GraphLayer gl = layerUtil.loadLayer(graph, layer);
+            gl.forEachTag(tag -> {
+                DiagramGraphUtil.tag(graph, startVertex, tag, true);
+                DiagramGraphUtil.tag(graph, endVertex, tag, true);
+            });
+        }
+        
+        return edge;
+    }
+    public void create(WriteGraph graph,  double[] start, double[] end, double padding) throws DatabaseException {
+        
+        Resource edge = create(graph, diagramResource, start, end, padding);
         // 7. Put the element on all the currently active layers if possible.
         if (glm != null) {
             putOnActiveLayer(graph, edge);
-            putOnActiveLayer(graph, startVertex);
-            putOnActiveLayer(graph, endVertex);
         }
         
         Layer0Utils.addCommentMetadata(graph, "Added edge " + edge);
@@ -68,26 +81,28 @@ public class DNEdgeBuilder {
         glm.putElementOnVisibleLayers(diagram, graph, res);
     }
 
-    private Resource getOrCreateVertex(WriteGraph graph, Collection<Resource> vertices, double[] coords, double padding) throws DatabaseException {
+    private static Resource getOrCreateVertex(WriteGraph graph, Resource diagramResource, Collection<Resource> vertices, double[] coords, double padding) throws DatabaseException {
         Resource vertex = null;
         double halfPadding = padding / 2;
+        double maxDistance = Double.MAX_VALUE;
         for (Resource vertx : vertices) {
             double[] existingCoords = graph.getRelatedValue2(vertx, DiagramResource.getInstance(graph).HasLocation, Bindings.DOUBLE_ARRAY);
             Rectangle2D existing = new Rectangle2D.Double(existingCoords[0] - halfPadding, existingCoords[1] - halfPadding, padding, padding);
             Rectangle2D tobecreated = new Rectangle2D.Double(coords[0] - halfPadding, coords[1] - halfPadding, padding, padding);
             if (existing.intersects(tobecreated)) {
-                vertex = vertx;
-                break;
+                double dist = Math.sqrt((Math.pow(coords[0] - existingCoords[0], 2) + (Math.pow(coords[1] - existingCoords[1], 2))));
+                if (dist <= maxDistance) {
+                    vertex = vertx;
+                }
             }
         }
         if (vertex == null) {
             vertex = DistrictNetworkUtil.createVertex(graph, diagramResource, coords); 
-            AddElement.claimFreshElementName(graph, diagramResource, vertex);
         }
         return vertex;
     }
 
-    private Resource getOrCreateEdge(WriteGraph graph) throws DatabaseException {
+    private static Resource getOrCreateEdge(WriteGraph graph, Resource diagramResource) throws DatabaseException {
         return DistrictNetworkUtil.createEdge(graph, diagramResource);
     }
 
index 486f87596e9e4bab0fb7ea47bc1d8332a2f76682..47a7bc5f12570f26a55cf9182a19835329574150 100644 (file)
@@ -41,7 +41,7 @@ public class DistrictDiagramViewer extends DiagramViewer {
     public void initializeCanvasContext(CanvasContext ctx) {
         super.initializeCanvasContext(ctx);
         IHintContext h = ctx.getDefaultHintContext();
-        h.setHint(PanZoomRotateHandler.KEY_ZOOM_IN_LIMIT, 10000.0);
+        h.setHint(PanZoomRotateHandler.KEY_ZOOM_IN_LIMIT, 1000000.0);
         h.setHint(PanZoomRotateHandler.KEY_ZOOM_OUT_LIMIT, 0.01);
     }
 
index e30b4cb0892286810c3452e9e426137df2e5d887..c5021ff11a1ea40c012acf394a90162374a03405 100644 (file)
@@ -1,22 +1,25 @@
-package org.simantics.district.network.ui;\r
-\r
-import java.awt.geom.Path2D;\r
-import java.awt.geom.Rectangle2D;\r
-\r
-public class DistrictNetworkEdge {\r
-\r
-    private Path2D path;\r
-    \r
-    public DistrictNetworkEdge(Path2D path) {\r
-        this.path = path;\r
-    }\r
-\r
-    public Path2D getPath() {\r
-        return path;\r
-    }\r
-\r
-    public Rectangle2D getBounds(Rectangle2D rect) {\r
-        rect.setFrame(path.getBounds2D());\r
-        return rect;\r
-    }\r
-}\r
+package org.simantics.district.network.ui;
+
+import java.awt.geom.Path2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Point2D.Double;
+import java.awt.geom.Rectangle2D;
+
+public class DistrictNetworkEdge {
+
+    private Path2D path;
+
+    public DistrictNetworkEdge(Path2D path) {
+        this.path = path;
+    }
+
+    public Path2D getPath() {
+        return path;
+    }
+
+    public Rectangle2D getBounds(Rectangle2D rect) {
+        rect.setFrame(path.getBounds2D());
+        return rect;
+    }
+
+}
index cf10ffab7c85923d8824b94fcbaefb4363e17e1c..a7cd09ac63a522d3dfb6d740f9d67652fa527248 100644 (file)
@@ -1,6 +1,7 @@
 package org.simantics.district.network.ui.adapters;
 
 import java.awt.Color;
+import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
 import java.util.Collection;
 import java.util.Collections;
@@ -89,7 +90,6 @@ public class DistrictNetworkEdgeElement {
 
             return size;
         }
-        
     }
     
     static class DNEdgeConnectionHandler implements ConnectionHandler {
index 2899a0e7cf8db5911e54beb3ad1b9d39db55c2d3..c3058a0edf5518341c6389ca61ad188019a0b85c 100644 (file)
@@ -1,6 +1,7 @@
 package org.simantics.district.network.ui.adapters;
 
 import java.awt.geom.Path2D;
+import java.awt.geom.Point2D;
 
 import org.simantics.db.AsyncReadGraph;
 import org.simantics.db.ReadGraph;
@@ -20,9 +21,11 @@ import org.simantics.g2d.canvas.ICanvasContext;
 import org.simantics.g2d.diagram.DiagramHints;
 import org.simantics.g2d.diagram.IDiagram;
 import org.simantics.g2d.element.ElementClass;
+import org.simantics.g2d.element.ElementUtils;
 import org.simantics.g2d.element.IElement;
 import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;
 import org.simantics.g2d.layers.ILayersEditor;
+import org.simantics.maps.MapScalingTransform;
 
 public class DistrictNetworkEdgeElementFactory extends SyncElementFactory {
 
@@ -51,7 +54,7 @@ public class DistrictNetworkEdgeElementFactory extends SyncElementFactory {
         
         Resource startVertex = graph.getSingleObject(edgeResource, DN.HasStartVertex);
         Resource endVertex = graph.getSingleObject(edgeResource, DN.HasEndVertex);
-        
+
         // TODO: fix scale..
         double scale = 100000;
         
@@ -61,7 +64,7 @@ public class DistrictNetworkEdgeElementFactory extends SyncElementFactory {
         double startLat = ModelledCRS.latitudeToY(startCoords[1]) * scale;
         
         double[] endCoords = graph.getRelatedValue2(endVertex, DIA.HasLocation);
-        
+
         double endLon = ModelledCRS.longitudeToX(endCoords[0]) * scale;
         double endLat = ModelledCRS.latitudeToY(endCoords[1]) * scale;
         
diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/contributions/ChangeMappingTypeHandler.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/contributions/ChangeMappingTypeHandler.java
new file mode 100644 (file)
index 0000000..2f3aae4
--- /dev/null
@@ -0,0 +1,190 @@
+package org.simantics.district.network.ui.contributions;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Named;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.SelectionStatusDialog;
+import org.simantics.DatabaseJob;
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.SelectionHints;
+import org.simantics.db.request.Read;
+import org.simantics.district.network.ontology.DistrictNetworkResource;
+import org.simantics.district.network.ui.function.Functions;
+import org.simantics.district.network.ui.internal.Activator;
+import org.simantics.layer0.Layer0;
+import org.simantics.utils.ui.ISelectionUtils;
+
+public class ChangeMappingTypeHandler {
+
+    
+    @CanExecute
+    public boolean canExecute(@Named(IServiceConstants.ACTIVE_SELECTION) ISelection selection) {
+        List<Resource> elements = ISelectionUtils.getPossibleKeys(selection, SelectionHints.KEY_MAIN, Resource.class);
+        if (elements.size() < 1)
+            return false;
+        try {
+            return Simantics.getSession().syncRequest(new Read<Boolean>() {
+
+                @Override
+                public Boolean perform(ReadGraph graph) throws DatabaseException {
+                    Layer0 L0 = Layer0.getInstance(graph);
+                    Resource instanceOf = null;
+                    for (Resource element : elements) {
+                        if (instanceOf == null) {
+                            instanceOf = graph.getSingleObject(element, L0.InstanceOf);
+                        } else {
+                            Resource currentInstanceOf = graph.getSingleObject(element, L0.InstanceOf);
+                            if (!currentInstanceOf.equals(instanceOf)) {
+                                return false;
+                            }
+                        }
+                    }
+                    return true;
+                }
+            });
+        } catch (DatabaseException e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+    
+    @Execute
+    public void execute(@Named(IServiceConstants.ACTIVE_SELECTION) Object selection) {
+        final List<Resource> elements = ISelectionUtils.getPossibleKeys(selection, SelectionHints.KEY_MAIN, Resource.class);
+        if (elements.size() < 1)
+            return;
+        
+        SelectMappingDialog dialog = new SelectMappingDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), elements);
+        if (dialog.open() != Dialog.OK)
+            return;
+        
+        Resource mapping = dialog.getDefaultVertexMapping();
+        Job job = new DatabaseJob("Join selected vertices") {
+            
+            @Override
+            protected IStatus run(IProgressMonitor monitor) {
+                try {
+                    Simantics.getSession().syncRequest(new WriteRequest() {
+                        
+                        @Override
+                        public void perform(WriteGraph graph) throws DatabaseException {
+                            DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
+                            for (Resource element : elements) {
+                                graph.deny(element, DN.HasMapping);
+                                graph.claim(element, DN.HasMapping, mapping);
+                            }
+                        }
+                    });
+                } catch (DatabaseException e) {
+                    return new Status(IStatus.ERROR, Activator.PLUGIN_ID, getName() + " failed.", e);
+                }
+                return Status.OK_STATUS;
+            }
+        };
+        job.setUser(true);
+        job.schedule();
+    }
+    
+    private static class SelectMappingDialog extends SelectionStatusDialog {
+
+        private Combo vertexMappingCombo;
+        
+        private Composite composite;
+        
+        private List<Resource> elements;
+        private Map<String, Resource> vertexMappings = new HashMap<>();
+        
+        private Resource defaultVertexMapping;
+
+        protected SelectMappingDialog(Shell parentShell, List<Resource> elements) {
+            super(parentShell);
+            this.elements = elements;
+            setTitle("Select mappings for new DN diagram");
+        }
+
+        public Resource getDefaultVertexMapping() {
+            return defaultVertexMapping;
+        }
+
+        @Override
+        protected Control createDialogArea(Composite parent) {
+            composite = (Composite) super.createDialogArea(parent);
+            
+            createMappingsGroup(composite);
+            
+            // compute default values
+            Simantics.getSession().asyncRequest(new ReadRequest() {
+
+                @Override
+                public void run(ReadGraph graph) throws DatabaseException {
+                    DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
+                    Resource element = elements.get(0);
+                    if (graph.isInstanceOf(element, DN.Vertex)) {
+                        vertexMappings = Functions.getVertexMappings(graph, element);
+                    } else if (graph.isInstanceOf(element, DN.Edge)) {
+                        vertexMappings = Functions.getEdgeMappings(graph, element);
+                    }
+                    composite.getDisplay().asyncExec(() -> {
+                        vertexMappingCombo.setItems(vertexMappings.keySet().toArray(new String[vertexMappings.size()]));
+                        vertexMappingCombo.select(0);
+                    }); 
+                    
+                }
+            });
+            return composite;
+        }
+
+        @Override
+        protected void computeResult() {
+            defaultVertexMapping = vertexMappings.get(vertexMappingCombo.getItem(vertexMappingCombo.getSelectionIndex()));
+        }
+        
+        private void createMappingsGroup(Composite parent) {
+            Group group= new Group(parent, SWT.NONE);
+            group.setFont(parent.getFont());
+            group.setText("Default mappings");
+            GridDataFactory.fillDefaults().grab(true, false).applyTo(group);
+            group.setLayout(new GridLayout(1, false));
+            
+            Composite cmposite = new Composite(group, SWT.NONE);
+            cmposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+            cmposite.setLayout(new GridLayout(2, false));
+            
+            Label vertexMappingLabel = new Label(cmposite, SWT.NONE);
+            vertexMappingLabel.setText("Default vertex mapping");
+
+            vertexMappingCombo = new Combo(cmposite, SWT.READ_ONLY | SWT.BORDER);
+            GridDataFactory.fillDefaults().grab(true, false).applyTo(vertexMappingCombo);
+            
+        }
+    }
+}
index 4fc40dbb109253fb5a2a2bf01a9eea0624dc6013..627de3a62171b46eebe4b2407edb3285b5da5d73 100644 (file)
@@ -1,9 +1,12 @@
 package org.simantics.district.network.ui.function;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 import org.eclipse.jface.dialogs.Dialog;
@@ -32,6 +35,7 @@ import org.simantics.db.Resource;
 import org.simantics.db.Session;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.common.request.IndexRoot;
+import org.simantics.db.common.request.IndexRoots;
 import org.simantics.db.common.request.ObjectsWithType;
 import org.simantics.db.common.request.ReadRequest;
 import org.simantics.db.common.request.WriteRequest;
@@ -49,7 +53,6 @@ import org.simantics.modeling.ModelingUtils;
 import org.simantics.modeling.adapters.NewCompositeActionFactory;
 import org.simantics.modeling.typicals.TypicalUtil;
 import org.simantics.scl.reflection.annotations.SCLValue;
-import org.simantics.structural.stubs.StructuralResource2;
 import org.simantics.ui.workbench.action.DefaultActions;
 import org.simantics.utils.ui.SWTUtils;
 import org.slf4j.Logger;
@@ -446,7 +449,15 @@ public class Functions {
                 });
     }
 
-    public static void getDistrictDiagrams(ReadGraph graph) {
-        
+    public static Collection<Resource> getDistrictDiagrams(ReadGraph graph) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        Collection<Resource> indexRoots = graph.sync(new ObjectsWithType(Simantics.getProjectResource(), L0.ConsistsOf, L0.IndexRoot));
+        DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
+        Set<Resource> results = new HashSet<>();
+        for (Resource indexRoot : indexRoots) {
+            Collection<Resource> diagrams = ModelingUtils.searchByType(graph, indexRoot, DN.Diagram);
+            results.addAll(diagrams);
+        }
+        return results;
     }
 }
index 11d883e91d560c77a4ceb2297ff4d51988aa657e..9170fa15eb4c495535fe9a46105cc044ace194ab 100644 (file)
@@ -6,8 +6,12 @@ import java.awt.Graphics2D;
 import java.awt.RenderingHints;
 import java.awt.Stroke;
 import java.awt.geom.AffineTransform;
+import java.awt.geom.Path2D;
+import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 
+import org.simantics.district.network.ModelledCRS;
+import org.simantics.district.network.ontology.DistrictNetworkResource;
 import org.simantics.district.network.ui.DistrictNetworkEdge;
 import org.simantics.scenegraph.g2d.G2DNode;
 import org.simantics.scenegraph.utils.GeometryUtils;
@@ -67,7 +71,7 @@ public class DistrictNetworkEdgeNode extends G2DNode {
         }
         // render
         g2d.draw(edge.getPath());
-        
+
         // Reset
         g2d.setStroke(oldStroke);
         g2d.setColor(oldColor);
@@ -76,7 +80,7 @@ public class DistrictNetworkEdgeNode extends G2DNode {
         if (ot != null)
             g2d.setTransform(ot);
     }
-
+    
     private boolean isSelected() {
         return NodeUtil.isSelected(this, 1);
     }
index 86c71857f16a860d93498bcf534c70f0d5239f7a..e9d0713ddb2d4bb34758ad8e279cacae64308263 100644 (file)
@@ -6,8 +6,10 @@ import java.awt.Graphics2D;
 import java.awt.RenderingHints;
 import java.awt.Stroke;
 import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 
+import org.simantics.district.network.ModelledCRS;
 import org.simantics.district.network.ui.adapters.DistrictNetworkVertex;
 import org.simantics.scenegraph.g2d.G2DNode;
 import org.simantics.scenegraph.utils.GeometryUtils;
index 078c8ebbbcae7155c80c9090755c857ee5f3ea1d..ba22aa42aabc61dfa674cde72ed41a9b623d33ca 100644 (file)
@@ -11,6 +11,7 @@ public class MapRulerNode extends RulerNode {
     protected double modifyHorizontalValue(double value) {
         // TODO: fix scale!
         double scale = 100000;
+//        double scale = 1;
         return ModelledCRS.xToLongitude(value / scale);
     }
 
@@ -18,6 +19,7 @@ public class MapRulerNode extends RulerNode {
     protected double modifyVerticalValue(double value) {
         // TODO: fix scale!
         double scale = 100000;
+//        double scale = 1;
         return ModelledCRS.yToLatitude(value / scale);
     }
 
index 13bd2cbe9426a536e9ce3b8030a0a4b0ca1b5158..b2c157184f07cf0c96b9eb342b3dc438f7cf53b8 100644 (file)
@@ -164,6 +164,7 @@ public class NetworkDrawingNode extends G2DNode {
          */
         // TODO: fix scale
         double scale = 100000;
+//        double scale = 1;
         double startLat = ModelledCRS.yToLatitude(start.getY() / scale);
         double startLon = ModelledCRS.xToLongitude(start.getX() / scale);
         
index 12caba477724d4af843abc1e43413ab1536d0698..7bec07dc138507ae14f4b344081e8d5b5c9c4fcf 100644 (file)
@@ -55,6 +55,7 @@ public class DNTranslateMode extends TranslateMode {
                                 double y = at.getTranslateY();
                                 // TODO: Fix scale!
                                 double scale = 100000;
+//                                double scale = 1;
                                 double lat = ModelledCRS.yToLatitude(y / scale);
                                 double lon = ModelledCRS.xToLongitude(x / scale);
                                 
index 51580d23a94406f23aee34c0c0bc49aff7c35d09..47d74d8e09bd90c66c98ceb92c9c0681ea2cc53b 100644 (file)
@@ -11,5 +11,6 @@ Require-Bundle: org.simantics.db,
  org.simantics.db.common,
  org.simantics.db.layer0,
  org.simantics.district.maps,
- org.simantics.district.geotools;bundle-version="1.0.0"
+ org.simantics.district.geotools;bundle-version="1.0.0",
+ org.simantics.diagram
 Export-Package: org.simantics.district.network
index 94799a97382e57a23a31b404f64e785f7d751245..6155bf6fade9face371879bcd4ed246094991a3e 100644 (file)
@@ -10,6 +10,10 @@ import org.simantics.db.WriteGraph;
 import org.simantics.db.common.utils.OrderedSetUtils;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.diagram.synchronization.graph.AddElement;
+import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
+import org.simantics.diagram.synchronization.graph.layer.GraphLayer;
+import org.simantics.diagram.synchronization.graph.layer.IGraphLayerUtil;
 import org.simantics.district.network.ontology.DistrictNetworkResource;
 import org.simantics.layer0.Layer0;
 
@@ -27,10 +31,17 @@ public class DistrictNetworkUtil {
         
         OrderedSetUtils.add(graph, composite, edge);
         graph.claim(composite, L0.ConsistsOf, L0.PartOf, edge);
+        
+        AddElement.claimFreshElementName(graph, composite, edge);
         return edge;
     }
     
     public static Resource createVertex(WriteGraph graph, Resource composite, double[] coords) throws DatabaseException {
+        Resource defaultVertexMapping = graph.getPossibleObject(composite, DistrictNetworkResource.getInstance(graph).VertexDefaultMapping);
+        return createVertex(graph, composite, coords, defaultVertexMapping);
+    }
+    
+    public static Resource createVertex(WriteGraph graph, Resource composite, double[] coords, Resource mapping) throws DatabaseException {
         Layer0 L0 = Layer0.getInstance(graph);
         DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
         DiagramResource DIA = DiagramResource.getInstance(graph);
@@ -38,12 +49,23 @@ public class DistrictNetworkUtil {
         graph.claim(vertex, L0.InstanceOf, DN.Vertex);
         graph.claimLiteral(vertex, DIA.HasLocation, coords);
         
-        Resource defaultVertexMapping = graph.getPossibleObject(composite, DN.VertexDefaultMapping);
-        graph.claim(vertex, DN.HasMapping, defaultVertexMapping);
+        graph.claim(vertex, DN.HasMapping, mapping);
         
         OrderedSetUtils.add(graph, composite, vertex);
         graph.claim(composite, L0.ConsistsOf, L0.PartOf, vertex);
         
+        AddElement.claimFreshElementName(graph, composite, vertex);
+        
+        // We need to put GraphLayer to newLayers so...
+        for (Resource layer : graph.getObjects(composite, DiagramResource.getInstance(graph).HasLayer)) {
+            IGraphLayerUtil layerUtil = graph.adapt(graph.getSingleObject(layer, Layer0.getInstance(graph).InstanceOf), IGraphLayerUtil.class);
+            
+            GraphLayer gl = layerUtil.loadLayer(graph, layer);
+            gl.forEachTag(tag -> {
+                DiagramGraphUtil.tag(graph, vertex, tag, true);
+            });
+        }
+        
         return vertex;
     }
     
index 23e68f2b273453c7a2636f2331c2bd417028447c..55d850e5e9092ebe3a345674a5f838e9ea69d4f8 100644 (file)
@@ -28,12 +28,11 @@ public class ModelledCRS implements CRS {
         return dist;
     }
 
-    
     // TODO: these only work with Spherical Mercator
     public static double xToLongitude(double x) {
         return x;
     }
-    
+
     public static double yToLatitude(double y) {
         double rad = Math.toRadians(y);
         double sinh = Math.sinh(rad);
@@ -41,7 +40,7 @@ public class ModelledCRS implements CRS {
         double finald = Math.toDegrees(atan);
         return finald;
     }
-    
+
     public static double longitudeToX(double lon) {
         return lon;
     }
index cd46e1a517f5c57dcaf64acef5cfe6d8a5570740..4c1c9637941488b8560b4d66f708e68a64315ca9 100644 (file)
@@ -4,9 +4,13 @@ import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.simantics.district.maps.server.TileserverMapnikInstance;
 import org.simantics.district.maps.server.prefs.MapsServerPreferences;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class Activator implements BundleActivator {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(Activator.class);
+    
     public static final String PLUGIN_ID = "org.simantics.maps.server.ui";
     
     private static BundleContext context;
@@ -30,8 +34,8 @@ public class Activator implements BundleActivator {
             new Thread(() -> {
                 try {
                     TileserverMapnikInstance.get().start();
-                } catch (Exception e) {
-                    e.printStackTrace();
+                } catch (Throwable t) {
+                    LOGGER.error("Could not start integrated tile server", t);
                 }
             }).start();
         }
index eaeda86acb88b6acf71432b556a3aa81d5d42aed..a09545fbf6034587aa74e90f17e7c382e886df9d 100644 (file)
@@ -1,6 +1,7 @@
 package org.simantics.district.maps.server;
 
 import java.io.IOException;
+import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.nio.file.Path;
@@ -40,15 +41,18 @@ public class Activator implements BundleActivator {
     }
 
     public static Path getNodeJSRoot() throws IOException, URISyntaxException {
-        URL nodeURL = getContext().getBundle().getEntry("/node");
-        URL nodeFileURL = FileLocator.toFileURL(nodeURL);
-        return Paths.get(nodeFileURL.toURI());
+        return resolvePath("/node");
     }
     
     public static Path getTileserverMapnikRoot() throws IOException, URISyntaxException {
-        URL serverURL = getContext().getBundle().getEntry("/server");
-        URL serverFileURL = FileLocator.toFileURL(serverURL);
-        return Paths.get(serverFileURL.toURI());
+        return resolvePath("/server");
+    }
+    
+    private static Path resolvePath(String entry) throws IOException, URISyntaxException {
+        URL entryURL = getContext().getBundle().getEntry(entry);
+        URL entryFileURL = FileLocator.toFileURL(entryURL);
+        URI encodedUri = new URI(entryFileURL.getProtocol(), entryFileURL.getPath(), null).normalize();
+        return Paths.get(encodedUri);
     }
 
 }