--- /dev/null
+package org.simantics.district.network.ui.table;
+
+import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
+
+public class ColumnHeaderTableDataProvider implements IDataProvider {
+
+ @Override
+ public Object getDataValue(int columnIndex, int rowIndex) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void setDataValue(int columnIndex, int rowIndex, Object newValue) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public int getColumnCount() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getRowCount() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+}
--- /dev/null
+package org.simantics.district.network.ui.table;
+
+import java.util.Set;
+
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.coordinate.Range;
+import org.eclipse.nebula.widgets.nattable.ui.action.IKeyAction;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.events.KeyEvent;
+
+public class CustomPasteDataAction implements IKeyAction {
+
+ private DistrictCSVTable table;
+
+ public CustomPasteDataAction(DistrictCSVTable table) {
+ this.table = table;
+ }
+
+ @Override
+ public void run(NatTable natTable, KeyEvent event) {
+ Object data = table.cpb.getContents(TextTransfer.getInstance());
+ if (data instanceof String) {
+ String textData = (String) data;
+ String[][] fullData = computeData(textData);
+
+ int[] cols = table.selectionLayer.getSelectedColumnPositions();
+ int firstCol = cols[0];
+ int column = table.selectionLayer.getColumnIndexByPosition(firstCol);
+ Set<Range> ranges = table.selectionLayer.getSelectedRowPositions();
+ if (!ranges.isEmpty()) {
+ int rowPosition = ranges.iterator().next().start;
+ int[] columns = new int[fullData.length];
+ columns[0] = column;
+ for (int i = 1; i < fullData.length; i++)
+ columns[i] = table.selectionLayer.getColumnIndexByPosition(firstCol + i);
+ table.bodyDataLayer.doCommand(new CustomPasteDataCommand(table.bodyDataLayer, columns, rowPosition, fullData));
+ }
+ }
+ }
+
+ private static String[][] computeData(String textData) {
+ String separator;
+ if (textData.contains(",") && !textData.contains(";")) {
+ separator = ",";
+ } else if (textData.contains(";") && !textData.contains("\t")) {
+ separator = ";";
+ } else {
+ separator = "\\t";
+ }
+
+ textData = textData.replaceAll("\\r", "");
+
+ String[] rows = textData.split("\\n");
+
+ String[][] cells = new String[rows.length][];
+ for(int i=0;i<rows.length;++i)
+ cells[i] = rows[i].split(separator, -1);
+
+ String[][] fullData = cells; //transpose(cells);
+
+ return fullData;
+ }
+
+ private static String[][] transpose(String[][] cells) {
+ int rowCount = 0;
+ for(String[] cols : cells)
+ rowCount = Math.max(rowCount, cols.length);
+ String[][] result = new String[rowCount][cells.length];
+ for(int i=0;i<cells.length;++i) {
+ String[] cols = cells[i];
+ int j;
+ for(j=0;j<cols.length;++j)
+ result[j][i] = cols[j];
+ for(;j<rowCount;++j)
+ result[j][i] = "";
+ }
+ return result;
+
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.district.network.ui.table;
+
+import org.eclipse.nebula.widgets.nattable.command.AbstractMultiColumnCommand;
+import org.eclipse.nebula.widgets.nattable.command.ILayerCommand;
+import org.eclipse.nebula.widgets.nattable.layer.ILayer;
+
+public class CustomPasteDataCommand extends AbstractMultiColumnCommand {
+
+ int pasteRow;
+ String[][] data;
+
+ protected CustomPasteDataCommand(ILayer layer, int[] columnPositions, int pasteRow, String[][] data) {
+ super(layer, columnPositions);
+ this.pasteRow = pasteRow;
+ this.data = data;
+ }
+
+ protected CustomPasteDataCommand(CustomPasteDataCommand pasteDataCommand) {
+ super(pasteDataCommand);
+ this.pasteRow = pasteDataCommand.pasteRow;
+ this.data = pasteDataCommand.data;
+ }
+ @Override
+ public ILayerCommand cloneCommand() {
+ return new CustomPasteDataCommand(this);
+ }
+
+}
--- /dev/null
+package org.simantics.district.network.ui.table;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
+import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
+import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
+import org.eclipse.nebula.widgets.nattable.copy.command.CopyDataCommandHandler;
+import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
+import org.eclipse.nebula.widgets.nattable.freeze.CompositeFreezeLayer;
+import org.eclipse.nebula.widgets.nattable.freeze.FreezeLayer;
+import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
+import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
+import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultColumnHeaderDataLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
+import org.eclipse.nebula.widgets.nattable.group.ColumnGroupHeaderLayer;
+import org.eclipse.nebula.widgets.nattable.group.ColumnGroupModel;
+import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
+import org.eclipse.nebula.widgets.nattable.hover.HoverLayer;
+import org.eclipse.nebula.widgets.nattable.hover.config.BodyHoverStylingBindings;
+import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
+import org.eclipse.nebula.widgets.nattable.layer.ILayer;
+import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer;
+import org.eclipse.nebula.widgets.nattable.reorder.RowReorderLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry;
+import org.eclipse.nebula.widgets.nattable.ui.matcher.KeyEventMatcher;
+import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.widgets.Composite;
+
+public class DistrictCSVTable extends Composite {
+
+ NatTable table;
+ private TableDataProvider bodyDataProvider;
+ DataLayer bodyDataLayer;
+ private IConfigRegistry summaryConfigRegistry;
+ private IUniqueIndexLayer summaryRowLayer;
+ private ViewportLayer viewportLayer;
+ private CompositeFreezeLayer compositeFreezeLayer;
+ private FreezeLayer freezeLayer;
+ //private TableDataSortModel sortModel;
+ private ColumnHideShowLayer columnHideShowLayer;
+ private ColumnGroupModel columnGroupModel = new ColumnGroupModel();
+ private ColumnHeaderTableDataProvider columnHeaderDataProvider;
+ Clipboard cpb;
+ public SelectionLayer selectionLayer;
+
+ public DistrictCSVTable(Composite parent, int style) {
+ super(parent, style);
+ defaultInitializeUI();
+ }
+
+ private void defaultInitializeUI() {
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(this);
+ GridLayoutFactory.fillDefaults().numColumns(1).applyTo(this);
+ createTable(this);
+ }
+
+ private void createTable(Composite parent) {
+
+ // build the body layer stack
+ // Usually you would create a new layer stack by extending AbstractIndexLayerTransform and
+ // setting the ViewportLayer as underlying layer. But in this case using the ViewportLayer
+ // directly as body layer is also working.
+ bodyDataProvider = new TableDataProvider();
+ bodyDataLayer = new DataLayer(bodyDataProvider);
+
+ RowReorderLayer rowReorderLayer =
+ new RowReorderLayer(columnHideShowLayer = new ColumnHideShowLayer(bodyDataLayer));
+
+ HoverLayer hoverLayer = new HoverLayer(rowReorderLayer, false);
+ // we need to ensure that the hover styling is removed when the mouse
+ // cursor moves out of the cell area
+ hoverLayer.addConfiguration(new BodyHoverStylingBindings(hoverLayer));
+
+ selectionLayer = new SelectionLayer(hoverLayer);
+ viewportLayer = new ViewportLayer(selectionLayer);
+ viewportLayer.setRegionName(GridRegion.BODY);
+ freezeLayer = new FreezeLayer(selectionLayer);
+ compositeFreezeLayer = new CompositeFreezeLayer(freezeLayer, viewportLayer, selectionLayer);
+
+ // build the column header layer
+ columnHeaderDataProvider = new ColumnHeaderTableDataProvider();
+ DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);
+ columnHeaderDataLayer.setRowsResizableByDefault(false);
+ columnHeaderDataLayer.setColumnsResizableByDefault(true);
+ ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, compositeFreezeLayer, selectionLayer);
+ ColumnGroupHeaderLayer columnGroupHeaderLayer = new ColumnGroupHeaderLayer(columnHeaderLayer, selectionLayer, columnGroupModel);
+ columnGroupHeaderLayer.setCalculateHeight(true);
+
+ // build the row header layer
+ IDataProvider rowHeaderDataProvider = new RowHeaderTableDataProvider(bodyDataProvider);
+ DataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
+ rowHeaderDataLayer.setRowsResizableByDefault(false);
+ rowHeaderDataLayer.setColumnsResizableByDefault(false);
+ RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, compositeFreezeLayer, selectionLayer);
+
+ // build the corner layer
+ IDataProvider cornerDataProvider = new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider);
+ DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
+ ILayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, columnGroupHeaderLayer);
+
+ // build the grid layer
+ GridLayer gridLayer = new GridLayer(compositeFreezeLayer, columnGroupHeaderLayer, rowHeaderLayer, cornerLayer);
+
+ table = new NatTable(parent, NatTable.DEFAULT_STYLE_OPTIONS | SWT.BORDER, gridLayer, false);
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(table);
+
+ // Register a CopyDataCommandHandler that also copies the headers and
+ // uses the configured IDisplayConverters
+ CopyDataCommandHandler copyHandler = new CopyDataCommandHandler(
+ selectionLayer,
+ columnHeaderDataLayer,
+ rowHeaderDataLayer);
+ copyHandler.setCopyFormattedText(true);
+ gridLayer.registerCommandHandler(copyHandler);
+
+ // initialize paste handler with SWT clipboard
+ cpb = new Clipboard(getDisplay());
+ PasteDataCommandHandler pasteHandler = new PasteDataCommandHandler(bodyDataProvider, bodyDataLayer, selectionLayer, cpb);
+ bodyDataLayer.registerCommandHandler(pasteHandler);
+
+ table.addConfiguration(new DefaultNatTableStyleConfiguration());
+ table.addConfiguration(new EditingSupportConfiguration(bodyDataProvider));
+
+ table.addConfiguration(new AbstractRegistryConfiguration() {
+
+ @Override
+ public void configureRegistry(IConfigRegistry configRegistry) {
+ }
+
+ @Override
+ public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
+ super.configureUiBindings(uiBindingRegistry);
+ // ui binding to perform a paste action on pressing CTRL+V
+ uiBindingRegistry.registerFirstKeyBinding(new KeyEventMatcher(SWT.MOD1, 'v'), new CustomPasteDataAction(DistrictCSVTable.this));
+ }
+ });
+
+ table.configure();
+ }
+
+ @Override
+ public void dispose() {
+ cpb.dispose();
+ super.dispose();
+ }
+
+ public String[][] getCurrentData() {
+ return bodyDataProvider.getCurrentData();
+ }
+
+}
--- /dev/null
+package org.simantics.district.network.ui.table;
+
+import org.eclipse.swt.widgets.Composite;
+
+public class DistrictCSVTableUI extends Composite {
+
+ public DistrictCSVTableUI(Composite parent, int style) {
+ super(parent, style);
+ }
+
+}
--- /dev/null
+package org.simantics.district.network.ui.table;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MHandledToolItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.swt.widgets.Composite;
+
+public class DistrictCSVTableView {
+
+ @Inject ESelectionService selectionService;
+
+ private DistrictCSVTable table;
+
+ @Inject
+ public void init(MPart part, MApplication app) {
+ MToolBar toolBar = MMenuFactory.INSTANCE.createToolBar();
+ toolBar.setToBeRendered(true);
+ toolBar.getChildren().add(createImportCSVDataToolItem(app));
+ part.setToolbar(toolBar);
+ }
+
+ private MHandledToolItem createImportCSVDataToolItem(MApplication app) {
+ MHandledToolItem createHandledToolItem = MMenuFactory.INSTANCE.createHandledToolItem();
+ // Command is contributed via fragment
+ createHandledToolItem.setCommand(app.getCommand("org.simantics.district.network.ui.command.importcsv")); //$NON-NLS-1$
+ createHandledToolItem.setLabel("Import CSV");
+ createHandledToolItem.setIconURI("platform:/plugin/com.famfamfam.silk/icons/table_edit.png"); //$NON-NLS-1$
+ return createHandledToolItem;
+ }
+
+ @PostConstruct
+ public void postConstruct(Composite parent) {
+ table = new DistrictCSVTable(parent, 0);
+
+ }
+
+ @PreDestroy
+ public void dispose() {
+ table.dispose();
+ table = null;
+ }
+
+ public String[][] getCurrentData() {
+ return table.getCurrentData();
+ }
+}
--- /dev/null
+package org.simantics.district.network.ui.table;
+
+import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
+import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
+import org.eclipse.nebula.widgets.nattable.config.IEditableRule;
+import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
+
+public class EditingSupportConfiguration extends AbstractRegistryConfiguration {
+
+ private TableDataProvider bodyDataProvider;
+
+ public EditingSupportConfiguration(TableDataProvider bodyDataProvider) {
+ this.bodyDataProvider = bodyDataProvider;
+ }
+
+ @Override
+ public void configureRegistry(IConfigRegistry configRegistry) {
+ configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITABLE_RULE, new IEditableRule() {
+ @Override
+ public boolean isEditable(ILayerCell cell, IConfigRegistry configRegistry) {
+ return bodyDataProvider.isEditable(cell.getColumnIndex(), cell.getRowIndex());
+ }
+
+ @Override
+ public boolean isEditable(int columnIndex, int rowIndex) {
+ return bodyDataProvider.isEditable(columnIndex, rowIndex);
+ }
+ });
+ }
+
+}
--- /dev/null
+package org.simantics.district.network.ui.table;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+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.dialogs.SelectionStatusDialog;
+import org.geotools.geometry.DirectPosition2D;
+import org.geotools.referencing.CRS;
+import org.opengis.geometry.DirectPosition;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.MathTransform;
+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.IndexRoot;
+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.request.PossibleActiveModel;
+import org.simantics.district.network.DistrictNetworkUtil;
+import org.simantics.district.network.ui.function.Functions;
+import org.simantics.modeling.ModelingResources;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ImportCSVHandler {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ImportCSVHandler.class);
+
+ @Inject
+ EPartService partService;
+
+ @Execute
+ public void execute(@Named(IServiceConstants.ACTIVE_SHELL) Shell s) {
+ // here we can import based on the current CSV table data
+ MPart activePart = partService.getActivePart();
+ Object object = activePart.getObject();
+ // this object is the part wrapped by e4part
+ DistrictCSVTableView view = (DistrictCSVTableView) object;
+ String[][] data = view.getCurrentData();
+
+ SelectionDialog d = new SelectionDialog(s);
+
+ if (d.open() == Dialog.CANCEL)
+ return;
+
+ String sourceEPSGCRS = d.getSourceCRS();//"EPSG:3067";
+
+ Resource targetDiagram = d.getTargetDiagram();
+ Resource mappingType = d.getMappingType();
+
+ try {
+ MathTransform transform = null;
+ boolean doTransform = false;
+ // if sourceEPSGCRS is empty || null then ignore transformation
+ if (sourceEPSGCRS != null && !sourceEPSGCRS.isEmpty()) {
+ CoordinateReferenceSystem sourceCRS = CRS.decode(sourceEPSGCRS);
+ CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326");
+ transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
+ doTransform = true;
+ }
+
+ final MathTransform finalTransform = transform;
+
+ int x = xColumn(data);
+ int y = yColumn(data);
+ int z = zColumn(data);
+
+ Simantics.getSession().asyncRequest(new WriteRequest() {
+
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ for (int i = 1; i < data.length; i++) {
+ try {
+ String[] rows = data[i];
+ String xCoords = rows[x];
+ String yCoords = rows[y];
+ double xCoord = Double.parseDouble(xCoords);
+ double yCoord = Double.parseDouble(yCoords);
+ DirectPosition2D targetPos = new DirectPosition2D();
+ DirectPosition2D sourcePos = new DirectPosition2D(xCoord, yCoord);
+ DirectPosition res = finalTransform.transform(sourcePos, targetPos);
+ double[] coords = res.getCoordinate();
+ flipAxes(coords);
+ Resource vertex = DistrictNetworkUtil.createVertex(graph, targetDiagram, coords, z, mappingType);
+ } catch (Exception e) {
+ LOGGER.error("", e);
+ }
+ }
+ }
+ });
+ } catch (Exception e) {
+ LOGGER.error("", e);
+ }
+
+
+ }
+
+ private static void flipAxes(double[] coords) {
+ double tmp = coords[0];
+ coords[0] = coords[1];
+ coords[1] = tmp;
+ }
+
+
+ private int zColumn(String[][] data) {
+ return column("z", data);
+ }
+
+ private int yColumn(String[][] data) {
+ return column("y", data);
+ }
+
+ private int xColumn(String[][] data) {
+ return column("x", data);
+ }
+
+ private int column(String expected, String[][] data) {
+ String[] columns = data[0]; // first row should be headers
+ for (int i = 0; i < columns.length; i++) {
+ String col = columns[i];
+ if (col.equals(expected)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private static class SelectionDialog extends SelectionStatusDialog {
+
+ private Map<String, Resource> diagrams = new HashMap<>();
+ private Map<String, Resource> vertexMappings = new HashMap<>();
+
+ private Composite composite;
+ private Combo networkDiagramSelectionCombo;
+ private Combo sourceCRSCombo;
+ private Combo vertexMappingCombo;
+ private String sourceCRS;
+ private Resource diagram;
+ private Resource mapping;
+
+ public SelectionDialog(Shell parent) {
+ super(parent);
+ }
+
+ public Resource getMappingType() {
+ return mapping;
+ }
+
+ public Resource getTargetDiagram() {
+ return diagram;
+ }
+
+ public String getSourceCRS() {
+ return "EPSG:" + sourceCRS;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ composite = (Composite) super.createDialogArea(parent);
+ createMappingsGroup(composite);
+ computeContent();
+ return composite;
+ }
+
+ private void computeContent() {
+ Simantics.getSession().asyncRequest(new ReadRequest() {
+
+ @Override
+ public void run(ReadGraph graph) throws DatabaseException {
+
+ Resource indexRoot = graph.sync(new IndexRoot(graph.sync(new PossibleActiveModel(Simantics.getProjectResource()))));
+ vertexMappings = Functions.getVertexMappings(graph, indexRoot);
+
+ Collection<Resource> diagramss = Functions.getDistrictDiagrams(graph);
+ ModelingResources MOD = ModelingResources.getInstance(graph);
+ Resource projectResource = Simantics.getProjectResource();
+ String projectURI = graph.getURI(projectResource);
+ for (Resource diagram : diagramss) {
+ Resource composite = graph.getSingleObject(diagram, MOD.DiagramToComposite);
+ String compositeURI = graph.getURI(composite);
+ String path = compositeURI.replace(projectURI, "");
+ diagrams.put(path, diagram);
+ }
+
+ composite.getDisplay().asyncExec(() -> {
+
+ vertexMappingCombo.setItems(vertexMappings.keySet().toArray(new String[vertexMappings.size()]));
+
+ networkDiagramSelectionCombo.setItems(diagrams.keySet().toArray(new String[diagrams.size()]));
+ if (diagrams.size() > 0) {
+ networkDiagramSelectionCombo.select(0);
+ }
+ Set<String> codes = CRS.getSupportedCodes("EPSG");
+ sourceCRSCombo.setItems(codes.toArray(new String[codes.size()]));
+ sourceCRSCombo.addModifyListener(new ModifyListener() {
+
+ @Override
+ public void modifyText(ModifyEvent e) {
+ String currentText = sourceCRSCombo.getText();
+ if (codes.contains(currentText)) {
+ // Select this
+ String[] items = sourceCRSCombo.getItems();
+ int i;
+ for (i = 0; i < items.length; i++) {
+ String item = items[i];
+ if (currentText.equals(item)) {
+ break;
+ }
+ }
+ if (i != 0) {
+ sourceCRSCombo.select(i);
+ } else {
+ System.err.println("Should not happen");
+ }
+ }
+ }
+ });
+ });
+ }
+ });
+ }
+
+ private void createMappingsGroup(Composite parent) {
+ Group group= new Group(parent, SWT.NONE);
+ group.setFont(parent.getFont());
+ group.setText("Select Diagram & CRS");
+ 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("Select Vertex Mapping");
+
+ vertexMappingCombo = new Combo(cmposite, SWT.READ_ONLY | SWT.BORDER);
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(vertexMappingCombo);
+
+ Label selectNetworkDiagramLabel = new Label(cmposite, SWT.NONE);
+ selectNetworkDiagramLabel.setText("Select Network Diagram");
+
+ networkDiagramSelectionCombo = new Combo(cmposite, SWT.READ_ONLY | SWT.BORDER);
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(networkDiagramSelectionCombo);
+
+ Label label = new Label(cmposite, SWT.NONE);
+ label.setText("Select Source Coordinate Reference System");
+
+ sourceCRSCombo = new Combo(cmposite, SWT.NONE);
+ sourceCRSCombo.setToolTipText("Select the coordinate reference system that is used in the source material for possible transformation to target coordinate reference system (EPSG:4326)");
+
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(sourceCRSCombo);
+ }
+
+ @Override
+ protected void computeResult() {
+ mapping = vertexMappings.get(vertexMappingCombo.getItem(vertexMappingCombo.getSelectionIndex()));
+ diagram = diagrams.get(networkDiagramSelectionCombo.getItem(networkDiagramSelectionCombo.getSelectionIndex()));
+ sourceCRS = sourceCRSCombo.getItem(sourceCRSCombo.getSelectionIndex());
+ }
+ }
+}
--- /dev/null
+package org.simantics.district.network.ui.table;
+
+import java.util.Collection;
+
+import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
+import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
+import org.eclipse.nebula.widgets.nattable.layer.event.ColumnVisualUpdateEvent;
+import org.eclipse.nebula.widgets.nattable.layer.event.StructuralRefreshEvent;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.swt.dnd.Clipboard;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PasteDataCommandHandler extends AbstractLayerCommandHandler<CustomPasteDataCommand> {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(PasteDataCommandHandler.class);
+
+ private final SelectionLayer selectionLayer;
+ private final DataLayer dataLayer;
+ private final Clipboard cpb;
+ private final TableDataProvider provider;
+
+ public PasteDataCommandHandler(TableDataProvider provider, DataLayer dataLayer, SelectionLayer selectionLayer, Clipboard cpb) {
+ this.provider = provider;
+ this.dataLayer = dataLayer;
+ this.selectionLayer = selectionLayer;
+ this.cpb = cpb;
+ }
+
+ @Override
+ public Class<CustomPasteDataCommand> getCommandClass() {
+ return CustomPasteDataCommand.class;
+ }
+
+ @Override
+ protected boolean doCommand(CustomPasteDataCommand command) {
+ String[][] fullData = command.data;
+ int pasteRow = command.pasteRow;
+ Collection<Integer> pasteColumn = command.getColumnPositions();
+ if (pasteRow > -1) {
+ provider.setDataValues(pasteColumn, pasteRow, fullData);
+ dataLayer.fireLayerEvent(new StructuralRefreshEvent(dataLayer));
+ }
+ return true;
+ }
+}
+
--- /dev/null
+package org.simantics.district.network.ui.table;
+
+import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
+
+public class RowHeaderTableDataProvider implements IDataProvider {
+
+ protected final IDataProvider bodyDataProvider;
+
+ public RowHeaderTableDataProvider(IDataProvider bodyDataProvider) {
+ this.bodyDataProvider = bodyDataProvider;
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 1;
+ }
+
+ @Override
+ public int getRowCount() {
+ return this.bodyDataProvider.getRowCount();
+ }
+
+ @Override
+ public Object getDataValue(int columnIndex, int rowIndex) {
+ return Integer.valueOf(rowIndex + 1);
+ }
+
+ @Override
+ public void setDataValue(int columnIndex, int rowIndex, Object newValue) {
+ throw new UnsupportedOperationException();
+ }
+
+}
--- /dev/null
+package org.simantics.district.network.ui.table;
+
+import java.util.Collection;
+
+import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
+
+public class TableDataProvider implements IDataProvider {
+
+ private String[][] data = null;
+
+ @Override
+ public Object getDataValue(int columnIndex, int rowIndex) {
+ if (data == null) {
+ return null;
+ } else {
+ return data[rowIndex][columnIndex];
+ }
+ }
+
+ @Override
+ public void setDataValue(int columnIndex, int rowIndex, Object newValue) {
+
+ }
+
+ @Override
+ public int getColumnCount() {
+ if (data == null) {
+ return 10;
+ } else {
+ return data[0].length;
+ }
+ }
+
+ @Override
+ public int getRowCount() {
+ if (data == null) {
+ return 10;
+ } else {
+ return data.length;
+ }
+ }
+
+ public boolean isEditable(int columnIndex, int rowIndex) {
+ return false;
+ }
+
+ public void setDataValues(Collection<Integer> pasteColumn, int pasteRow, String[][] fullData) {
+ // start always from row index 0 and column index 0
+ this.data = fullData;
+ }
+
+ public String[][] getCurrentData() {
+ return data;
+ }
+
+}