mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-11 01:32:08 +10:00
Added 'File' -> 'Import Netlist' option that can import components from
a Tango PCB file
This commit is contained in:
@@ -23,6 +23,7 @@ package org.diylc.common;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.diylc.netlist.INetlistParser;
|
||||
import org.diylc.netlist.Netlist;
|
||||
|
||||
/**
|
||||
@@ -47,5 +48,11 @@ public interface INetlistProcessor {
|
||||
*/
|
||||
List<INetlistAnalyzer> getNetlistAnalyzers();
|
||||
|
||||
/**
|
||||
* Finds all available {@link INetlistParser} implementations.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<INetlistParser> getNetlistParserDefinitions();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
*
|
||||
* This file is part of DIYLC.
|
||||
*
|
||||
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License as published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.diylc.netlist;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
|
||||
public abstract class AbstractNetlistParser implements INetlistParser {
|
||||
|
||||
private static Size X_OFFSET = new Size(1.5d, SizeUnit.in);
|
||||
private static Size Y_OFFSET = new Size(0.3d, SizeUnit.in);
|
||||
private static int ROW_COUNT = 15;
|
||||
|
||||
public List<ParsedNetlistEntry> parseFile(String fileName, List<String> outputWarnings) throws NetlistParseException {
|
||||
String content;
|
||||
try {
|
||||
content = new String(Files.readAllBytes(Paths.get(fileName)));
|
||||
} catch (IOException e) {
|
||||
throw new NetlistParseException("Error reading file", e);
|
||||
}
|
||||
|
||||
return parse(content, outputWarnings);
|
||||
}
|
||||
|
||||
public List<ParsedNetlistEntry> parse(String content, List<String> outputWarnings) throws NetlistParseException {
|
||||
List<ParsedNetlistEntry> result = new ArrayList<ParsedNetlistEntry>();
|
||||
|
||||
Pattern pattern = Pattern.compile(getItemRegex(), Pattern.MULTILINE | Pattern.DOTALL);
|
||||
Matcher matcher = pattern.matcher(content);
|
||||
while (matcher.find()) {
|
||||
String type;
|
||||
try {
|
||||
type = matcher.group("Type").trim();
|
||||
} catch (Exception e) {
|
||||
outputWarnings.add("'Type' group not found.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == null) {
|
||||
outputWarnings.add("'Type' group not found.");
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, Object> valueMap = new HashMap<String, Object>();
|
||||
List<Class<?>> typeCandidates = getComponentTypeCandidates(type, valueMap);
|
||||
if (typeCandidates == null) {
|
||||
outputWarnings.add("Type mappings not found for " + type + ".");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (String propertyName : getPropertyNames()) {
|
||||
String valueStr = matcher.group(propertyName).trim();
|
||||
try {
|
||||
Object value = parseValue(type, propertyName, valueStr);
|
||||
valueMap.put(propertyName, value);
|
||||
} catch (Exception e) {
|
||||
outputWarnings
|
||||
.add("Error while parsing value for " + type + "." + propertyName + " = " + valueStr);
|
||||
}
|
||||
}
|
||||
|
||||
result.add(new ParsedNetlistEntry(typeCandidates, type, valueMap));
|
||||
}
|
||||
|
||||
Collections.sort(result, new Comparator<ParsedNetlistEntry>() {
|
||||
|
||||
@Override
|
||||
public int compare(ParsedNetlistEntry o1, ParsedNetlistEntry o2) {
|
||||
int comp = o1.getRawType().compareToIgnoreCase(o2.getRawType());
|
||||
if (comp == 0 && o1.getValues().containsKey("Name") && o2.getValues().containsKey("Name"))
|
||||
comp = o1.getValues().get("Name").toString().compareToIgnoreCase(o2.getValues().get("Name").toString());
|
||||
return comp;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<IDIYComponent<?>> generateComponents(List<ParsedNetlistComponent> components,
|
||||
List<String> outputWarnings) {
|
||||
double dx = 0;
|
||||
double dy = 0;
|
||||
List<IDIYComponent<?>> result = new ArrayList<IDIYComponent<?>>();
|
||||
for (int i = 0; i < components.size(); i++) {
|
||||
ParsedNetlistComponent parsedComponent = components.get(i);
|
||||
if (parsedComponent.getType() == null) {
|
||||
outputWarnings.add("Type not selected for " + parsedComponent.getValues().get("Name"));
|
||||
continue;
|
||||
}
|
||||
Class<?> clazz = parsedComponent.getType();
|
||||
IDIYComponent<?> component;
|
||||
try {
|
||||
component = (IDIYComponent<?>) clazz.newInstance();
|
||||
} catch (Exception e) {
|
||||
outputWarnings.add(e.getMessage());
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < component.getControlPointCount(); j++) {
|
||||
Point2D p = component.getControlPoint(j);
|
||||
Point2D controlPoint = new Point2D.Double(p.getX() + dx, p.getY() + dy);
|
||||
component.setControlPoint(controlPoint, j);
|
||||
}
|
||||
|
||||
if (i > 0 && i % ROW_COUNT == 0) {
|
||||
dx += X_OFFSET.convertToPixels();
|
||||
dy = 0;
|
||||
} else {
|
||||
dy += Y_OFFSET.convertToPixels();
|
||||
}
|
||||
|
||||
Method[] methods = clazz.getMethods();
|
||||
for (Map.Entry<String, Object> value : parsedComponent.getValues().entrySet()) {
|
||||
try {
|
||||
Optional<Method> first = Arrays.stream(methods).filter(x -> x.getName().equals("set" + value.getKey())).findFirst();
|
||||
if (first.isPresent()) {
|
||||
Method setter = first.get();
|
||||
setter.invoke(component, value.getValue());
|
||||
} else {
|
||||
outputWarnings.add("No setter found for " + value.getKey());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
outputWarnings.add("Error setting " + value.getKey() + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
result.add(component);
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
*
|
||||
* This file is part of DIYLC.
|
||||
*
|
||||
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License as published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.diylc.netlist;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
*
|
||||
* This file is part of DIYLC.
|
||||
*
|
||||
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License as published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
public interface INetlistParser {
|
||||
|
||||
String getName();
|
||||
|
||||
String getFileExt();
|
||||
|
||||
String getItemRegex();
|
||||
|
||||
List<Class<?>> getComponentTypeCandidates(String type, Map<String, Object> additionalOutputs);
|
||||
|
||||
List<String> getPropertyNames();
|
||||
|
||||
Object parseValue(String type, String propertyName, String valueStr);
|
||||
|
||||
List<ParsedNetlistEntry> parseFile(String fileName, List<String> outputWarnings)
|
||||
throws NetlistParseException;
|
||||
|
||||
List<ParsedNetlistEntry> parse(String content, List<String> outputWarnings)
|
||||
throws NetlistParseException;
|
||||
|
||||
List<IDIYComponent<?>> generateComponents(List<ParsedNetlistComponent> components,
|
||||
List<String> outputWarnings);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
*
|
||||
* This file is part of DIYLC.
|
||||
*
|
||||
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License as published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.diylc.netlist;
|
||||
|
||||
public class NetlistParseException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public NetlistParseException() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public NetlistParseException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public NetlistParseException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public NetlistParseException(String message) {
|
||||
super(message);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public NetlistParseException(Throwable cause) {
|
||||
super(cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.diylc.netlist;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ParsedNetlistComponent {
|
||||
|
||||
public Class<?> type;
|
||||
public Map<String, Object> values;
|
||||
|
||||
public ParsedNetlistComponent() {
|
||||
}
|
||||
|
||||
public ParsedNetlistComponent(Class<?> type, Map<String, Object> values) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Map<String, Object> getValues() {
|
||||
return values;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.netlist;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ParsedNetlistEntry {
|
||||
|
||||
private List<Class<?>> typeCandidates;
|
||||
private Map<String, Object> values;
|
||||
private String rawType;
|
||||
|
||||
public ParsedNetlistEntry() {
|
||||
}
|
||||
|
||||
public ParsedNetlistEntry(List<Class<?>> typeCandidates, String rawType,
|
||||
Map<String, Object> values) {
|
||||
super();
|
||||
this.typeCandidates = typeCandidates;
|
||||
this.rawType = rawType;
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public List<Class<?>> getTypeCandidates() {
|
||||
return typeCandidates;
|
||||
}
|
||||
|
||||
public String getRawType() {
|
||||
return rawType;
|
||||
}
|
||||
|
||||
public Map<String, Object> getValues() {
|
||||
return values;
|
||||
}
|
||||
}
|
||||
@@ -83,6 +83,7 @@ import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
import org.diylc.lang.LangUtil;
|
||||
import org.diylc.netlist.Group;
|
||||
import org.diylc.netlist.INetlistParser;
|
||||
import org.diylc.netlist.Netlist;
|
||||
import org.diylc.netlist.NetlistAnalyzer;
|
||||
import org.diylc.netlist.Node;
|
||||
@@ -3403,6 +3404,34 @@ public class Presenter implements IPlugInPort {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<INetlistParser> getNetlistParserDefinitions() {
|
||||
Set<Class<?>> classes;
|
||||
try {
|
||||
classes = Utils.getClasses("org.diylc.netlist");
|
||||
List<INetlistParser> result = new ArrayList<INetlistParser>();
|
||||
|
||||
for (Class<?> clazz : classes) {
|
||||
if (!Modifier.isAbstract(clazz.getModifiers()) && INetlistParser.class.isAssignableFrom(clazz)) {
|
||||
result.add((INetlistParser) clazz.newInstance());
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(result, new Comparator<INetlistParser>() {
|
||||
|
||||
@Override
|
||||
public int compare(INetlistParser o1, INetlistParser o2) {
|
||||
return o1.getName().compareToIgnoreCase(o2.getName());
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not load INetlistParserDefinition implementations", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Test stuff
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3418,6 +3418,10 @@
|
||||
<releaseDate>2020-12-28 00:00:00.000 CET</releaseDate>
|
||||
<name></name>
|
||||
<changes>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>Added 'File' -> 'Import Netlist' option that can import components from a Tango PCB file</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>Português translation added (thanks Pedro Rizzi!)</description>
|
||||
|
||||
Reference in New Issue
Block a user