From 31bcbe46c93a576cd6ade673a745ea9cb28672da Mon Sep 17 00:00:00 2001 From: jsimomaa Date: Tue, 20 Dec 2016 17:25:07 +0200 Subject: [PATCH] Adding basic import utilities - WIP! --- org.simantics.district.feature/.project | 17 ++ .../build.properties | 1 + org.simantics.district.feature/feature.xml | 40 ++++ org.simantics.district.imports.ui/.classpath | 7 + org.simantics.district.imports.ui/.project | 28 +++ .../META-INF/MANIFEST.MF | 12 ++ .../build.properties | 5 + org.simantics.district.imports.ui/plugin.xml | 15 ++ .../district/imports/ui/CSVImportModel.java | 73 +++++++ .../district/imports/ui/CSVImportWizard.java | 38 ++++ .../imports/ui/CSVImportWizardPage.java | 185 ++++++++++++++++++ org.simantics.district.imports/.classpath | 12 ++ org.simantics.district.imports/.project | 34 ++++ .../META-INF/MANIFEST.MF | 10 + .../build.properties | 5 + .../lib/commons-csv-1.4-sources.jar | Bin 0 -> 45056 bytes .../lib/commons-csv-1.4.jar | Bin 0 -> 39978 bytes org.simantics.district.imports/pom.xml | 42 ++++ .../district/imports/DistrictImportUtils.java | 156 +++++++++++++++ org.simantics.district.ui.feature/.project | 17 ++ .../build.properties | 1 + org.simantics.district.ui.feature/feature.xml | 37 ++++ 22 files changed, 735 insertions(+) create mode 100644 org.simantics.district.feature/.project create mode 100644 org.simantics.district.feature/build.properties create mode 100644 org.simantics.district.feature/feature.xml create mode 100644 org.simantics.district.imports.ui/.classpath create mode 100644 org.simantics.district.imports.ui/.project create mode 100644 org.simantics.district.imports.ui/META-INF/MANIFEST.MF create mode 100644 org.simantics.district.imports.ui/build.properties create mode 100644 org.simantics.district.imports.ui/plugin.xml create mode 100644 org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportModel.java create mode 100644 org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizard.java create mode 100644 org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizardPage.java create mode 100644 org.simantics.district.imports/.classpath create mode 100644 org.simantics.district.imports/.project create mode 100644 org.simantics.district.imports/META-INF/MANIFEST.MF create mode 100644 org.simantics.district.imports/build.properties create mode 100644 org.simantics.district.imports/lib/commons-csv-1.4-sources.jar create mode 100644 org.simantics.district.imports/lib/commons-csv-1.4.jar create mode 100644 org.simantics.district.imports/pom.xml create mode 100644 org.simantics.district.imports/src/org/simantics/district/imports/DistrictImportUtils.java create mode 100644 org.simantics.district.ui.feature/.project create mode 100644 org.simantics.district.ui.feature/build.properties create mode 100644 org.simantics.district.ui.feature/feature.xml diff --git a/org.simantics.district.feature/.project b/org.simantics.district.feature/.project new file mode 100644 index 00000000..61ffe362 --- /dev/null +++ b/org.simantics.district.feature/.project @@ -0,0 +1,17 @@ + + + org.simantics.district.feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/org.simantics.district.feature/build.properties b/org.simantics.district.feature/build.properties new file mode 100644 index 00000000..82ab19c6 --- /dev/null +++ b/org.simantics.district.feature/build.properties @@ -0,0 +1 @@ +bin.includes = feature.xml diff --git a/org.simantics.district.feature/feature.xml b/org.simantics.district.feature/feature.xml new file mode 100644 index 00000000..57e342d4 --- /dev/null +++ b/org.simantics.district.feature/feature.xml @@ -0,0 +1,40 @@ + + + + + [Enter Feature Description here.] + + + + [Enter Copyright Description here.] + + + + [Enter License Description here.] + + + + + + + + + diff --git a/org.simantics.district.imports.ui/.classpath b/org.simantics.district.imports.ui/.classpath new file mode 100644 index 00000000..b862a296 --- /dev/null +++ b/org.simantics.district.imports.ui/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.simantics.district.imports.ui/.project b/org.simantics.district.imports.ui/.project new file mode 100644 index 00000000..9c9d811b --- /dev/null +++ b/org.simantics.district.imports.ui/.project @@ -0,0 +1,28 @@ + + + org.simantics.district.imports.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.simantics.district.imports.ui/META-INF/MANIFEST.MF b/org.simantics.district.imports.ui/META-INF/MANIFEST.MF new file mode 100644 index 00000000..fb65af54 --- /dev/null +++ b/org.simantics.district.imports.ui/META-INF/MANIFEST.MF @@ -0,0 +1,12 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Simantics District Import UI +Bundle-SymbolicName: org.simantics.district.imports.ui;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.eclipse.ui.ide, + org.eclipse.jface, + org.simantics.utils.ui, + org.simantics.district.imports;bundle-version="1.0.0", + org.simantics.db +Bundle-ActivationPolicy: lazy diff --git a/org.simantics.district.imports.ui/build.properties b/org.simantics.district.imports.ui/build.properties new file mode 100644 index 00000000..6f20375d --- /dev/null +++ b/org.simantics.district.imports.ui/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml diff --git a/org.simantics.district.imports.ui/plugin.xml b/org.simantics.district.imports.ui/plugin.xml new file mode 100644 index 00000000..fe77b996 --- /dev/null +++ b/org.simantics.district.imports.ui/plugin.xml @@ -0,0 +1,15 @@ + + + + + + + Imports CSV data to Simantics District network + + + + diff --git a/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportModel.java b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportModel.java new file mode 100644 index 00000000..50c427c4 --- /dev/null +++ b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportModel.java @@ -0,0 +1,73 @@ +package org.simantics.district.imports.ui; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.simantics.district.imports.DistrictImportUtils; +import org.simantics.district.imports.DistrictImportUtils.CSVHeader; + +public class CSVImportModel { + + private Path source; + private char delimiter; + private boolean read; + private Map delimiters; + + public CSVImportModel() { + delimiters = DistrictImportUtils.getSupportedCSVDelimiterFormats(); + } + + public void setSource(Path source) { + this.source = source; + } + + public void setDelimiter(char delimiter) { + this.delimiter = delimiter; + } + + public void setReadFirstAsHeader(boolean read) { + this.read = read; + } + + public Path getSource() { + return source; + } + + public Map> getHeaderAndRows(int amount) throws IOException { + if (source != null) + return DistrictImportUtils.readCSVHeaderAndRows(source, delimiter, read, amount); + else + return Collections.emptyMap(); + } + + public Map getHeader() throws IOException { + Map header = null; + if (source != null) + header = DistrictImportUtils.readCSVHeader(source, delimiter, read); + if (header == null) + header = Collections.emptyMap(); + return header; + } + + public boolean getReadFirstAsHeader() { + return read; + } + + public String[] getDelimiterFormats() { + return delimiters.keySet().toArray(new String[delimiters.size()]); + } + + public void setDelimiterByLabel(String item) { + setDelimiter(delimiters.get(item)); + } + + public List> readRows(int amount) throws IOException { + if (source != null) + return DistrictImportUtils.readRows(source, delimiter, read, amount); + else + return Collections.emptyList(); + } +} diff --git a/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizard.java b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizard.java new file mode 100644 index 00000000..97fa990a --- /dev/null +++ b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizard.java @@ -0,0 +1,38 @@ +package org.simantics.district.imports.ui; + +import java.io.IOException; +import java.nio.file.Path; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.ui.IImportWizard; +import org.eclipse.ui.IWorkbench; +import org.simantics.district.imports.DistrictImportUtils; + +public class CSVImportWizard extends Wizard implements IImportWizard { + + private CSVImportModel model; + + public CSVImportWizard() { + setWindowTitle("Import CSV data"); + } + + + @Override + public void init(IWorkbench workbench, IStructuredSelection selection) { + model = new CSVImportModel(); + addPage(new CSVImportWizardPage(model)); + } + + @Override + public boolean performFinish() { + Path csvFile = model.getSource(); + try { + DistrictImportUtils.importCSVAsLayer(csvFile); + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + +} diff --git a/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizardPage.java b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizardPage.java new file mode 100644 index 00000000..85eeb942 --- /dev/null +++ b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizardPage.java @@ -0,0 +1,185 @@ +package org.simantics.district.imports.ui; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.layout.TreeColumnLayout; +import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +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.GridData; +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.Layout; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.simantics.district.imports.DistrictImportUtils.CSVHeader; +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 { + + private CSVImportModel model; + private FileSelectionWidget csvSelection; + private Table headerTable; + private Button firstAsHeader; + private Combo delimiterCombo; + private TableColumnLayout tableColumnLayout; + private TableViewer tableViewer; + + protected CSVImportWizardPage(CSVImportModel model) { + super("Import CSV Data"); + this.model = model; + setMessage("Select CSV file to import"); + } + + @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); + + 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(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent 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(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + + } + }); + + + Composite tableComposite = new Composite(composite, SWT.BORDER); + TreeColumnLayout treeColumnLayout = new TreeColumnLayout(); + tableComposite.setLayout(treeColumnLayout); + + tableViewer = new TableViewer(tableComposite, SWT.V_SCROLL | SWT.H_SCROLL); + ColumnViewerToolTipSupport.enableFor(tableViewer); + tableViewer.setContentProvider(new IContentProvider() { + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + + } + + @Override + public void dispose() { + + } + }); + + Table table = tableViewer.getTable(); + table.setHeaderVisible(true); + table.setLinesVisible(true); + + headerTable = new Table(tableComposite, SWT.NONE); + headerTable.setHeaderVisible(true); + headerTable.setLinesVisible(true); + GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(tableComposite); + + setControl(composite); + + updateHeaders(); + + setPageComplete(false); + } + + @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); + } + } else { + setPageComplete(false); + } + } + + private void updateHeaders() { + headerTable.setRedraw(false); + for (int i = 0; i < headerTable.getColumns().length; i++) { + TableColumn column = headerTable.getColumns()[i]; + column.dispose(); + } + for (int i = 0; i < headerTable.getItemCount(); i++) { + TableItem item = headerTable.getItem(i); + item.dispose(); + } + try { + Map> headerAndValues = model.getHeaderAndRows(5); + + int coo = headerTable.getColumns().length; + int count = headerTable.getColumnCount(); + + for (Map.Entry> 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()); + } + headerTable.setRedraw(true); + } + +} diff --git a/org.simantics.district.imports/.classpath b/org.simantics.district.imports/.classpath new file mode 100644 index 00000000..ac0cdbaf --- /dev/null +++ b/org.simantics.district.imports/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/org.simantics.district.imports/.project b/org.simantics.district.imports/.project new file mode 100644 index 00000000..aebad524 --- /dev/null +++ b/org.simantics.district.imports/.project @@ -0,0 +1,34 @@ + + + org.simantics.district.imports + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.simantics.district.imports/META-INF/MANIFEST.MF b/org.simantics.district.imports/META-INF/MANIFEST.MF new file mode 100644 index 00000000..50cc5d26 --- /dev/null +++ b/org.simantics.district.imports/META-INF/MANIFEST.MF @@ -0,0 +1,10 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Simantics District Imports +Bundle-SymbolicName: org.simantics.district.imports +Bundle-Version: 1.0.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.simantics.db +Export-Package: org.simantics.district.imports +Bundle-ClassPath: lib/commons-csv-1.4.jar, + . diff --git a/org.simantics.district.imports/build.properties b/org.simantics.district.imports/build.properties new file mode 100644 index 00000000..78db4425 --- /dev/null +++ b/org.simantics.district.imports/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + lib/commons-csv-1.4.jar diff --git a/org.simantics.district.imports/lib/commons-csv-1.4-sources.jar b/org.simantics.district.imports/lib/commons-csv-1.4-sources.jar new file mode 100644 index 0000000000000000000000000000000000000000..baf9b88fcb5a03b999a306455c1c62d4c276ac12 GIT binary patch literal 45056 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 literal 0 HcmV?d00001 diff --git a/org.simantics.district.imports/lib/commons-csv-1.4.jar b/org.simantics.district.imports/lib/commons-csv-1.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..e9eb0bd35ccf5876b3d2f1fce3afecdfc3cd12b7 GIT binary patch literal 39978 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 literal 0 HcmV?d00001 diff --git a/org.simantics.district.imports/pom.xml b/org.simantics.district.imports/pom.xml new file mode 100644 index 00000000..ed7ddaa2 --- /dev/null +++ b/org.simantics.district.imports/pom.xml @@ -0,0 +1,42 @@ + + 4.0.0 + org.simantics.district.imports + org.simantics.district.imports + 0.0.1-SNAPSHOT + eclipse-plugin + + + + UTF-8 + 0.25.0 + + + + + org.apache.commons + commons-csv + 1.4 + + + + + src + + + org.eclipse.tycho + tycho-maven-plugin + ${tycho-version} + true + + + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/org.simantics.district.imports/src/org/simantics/district/imports/DistrictImportUtils.java b/org.simantics.district.imports/src/org/simantics/district/imports/DistrictImportUtils.java new file mode 100644 index 00000000..7c0d998c --- /dev/null +++ b/org.simantics.district.imports/src/org/simantics/district/imports/DistrictImportUtils.java @@ -0,0 +1,156 @@ +package org.simantics.district.imports; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; +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))) { + Map header = parser.getHeaderMap(); + System.out.println(header); + } + return null; + } + + public static Map readCSVHeader(Path source, char delimiter, boolean firstAsHeader) throws IOException { + return readCSVHeader(source, CSVFormat.newFormat(delimiter), firstAsHeader); + } + + public static Map readCSVHeader(Path source, CSVFormat format, boolean firstAsHeader) throws IOException { + if (firstAsHeader) + format = format.withFirstRecordAsHeader(); + try (CSVParser parser = format.parse(Files.newBufferedReader(source))) { + return parser.getHeaderMap(); + } + } + + + public static Map getSupportedCSVDelimiterFormats() { + Map delimiters = new HashMap<>(); + delimiters.put("COMMA", ','); + delimiters.put("SEMICOMMA", ';'); + return delimiters; + } + + public static List> readRows(Path source, char delimiter, boolean firstAsHeader, int amount) throws IOException { + return readRows(source, CSVFormat.newFormat(delimiter), firstAsHeader, amount); + } + + public static List> readRows(Path source, CSVFormat format, boolean firstAsHeader, int amount) throws IOException { + if (firstAsHeader) + format = format.withFirstRecordAsHeader(); + try (CSVParser parser = format.parse(Files.newBufferedReader(source))) { + int start = 0; + List> results = new ArrayList<>(amount); + Iterator iter = parser.iterator(); + while (start < amount && iter.hasNext()) { + CSVRecord record = iter.next(); + results.add(record.toMap()); + start++; + } + return results; + } + } + + + public static Map> readCSVHeaderAndRows(Path source, char delimiter, boolean firstAsHeader, int amount) throws IOException { + Map> results = new HashMap<>(); + CSVFormat format = CSVFormat.newFormat(delimiter); + if (firstAsHeader) + format = format.withFirstRecordAsHeader(); + try (CSVParser parser = format.parse(Files.newBufferedReader(source))) { + Map headers = parser.getHeaderMap(); + if (headers != null && !headers.isEmpty()) { + for (int index = 0; index < headers.size(); index++) { + for (String head : headers.keySet()) { + results.put(new CSVHeader(head, index), new ArrayList<>()); + } + } + } + + Iterator records = parser.iterator(); + int rows = 0; + while (rows < amount && records.hasNext()) { + CSVRecord record = records.next(); + for (int j = 0; j < record.size(); j++) { + String value = record.get(j); + String header = Integer.toString(j); + CSVHeader csvHeader = new CSVHeader(header, j); + List vals = results.get(csvHeader); + if (vals == null) { + vals = new ArrayList<>(); + results.put(csvHeader, vals); + } + vals.add(value); + } + rows++; + } + } + return results; + } + + public static class CSVHeader { + + private final String header; + private final int index; + + public CSVHeader(String header, int index) { + this.header = header; + this.index = index; + } + + public String getHeader() { + return header; + } + + public int getIndex() { + return index; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((header == null) ? 0 : header.hashCode()); + result = prime * result + index; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CSVHeader other = (CSVHeader) obj; + if (header == null) { + if (other.header != null) + return false; + } else if (!header.equals(other.header)) + return false; + if (index != other.index) + return false; + return true; + } + } + +} diff --git a/org.simantics.district.ui.feature/.project b/org.simantics.district.ui.feature/.project new file mode 100644 index 00000000..e8ca237e --- /dev/null +++ b/org.simantics.district.ui.feature/.project @@ -0,0 +1,17 @@ + + + org.simantics.district.ui.feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/org.simantics.district.ui.feature/build.properties b/org.simantics.district.ui.feature/build.properties new file mode 100644 index 00000000..82ab19c6 --- /dev/null +++ b/org.simantics.district.ui.feature/build.properties @@ -0,0 +1 @@ +bin.includes = feature.xml diff --git a/org.simantics.district.ui.feature/feature.xml b/org.simantics.district.ui.feature/feature.xml new file mode 100644 index 00000000..e43314c8 --- /dev/null +++ b/org.simantics.district.ui.feature/feature.xml @@ -0,0 +1,37 @@ + + + + + [Enter Feature Description here.] + + + + [Enter Copyright Description here.] + + + + [Enter License Description here.] + + + + + + + + + -- 2.47.1