first nested model solution is working

This commit is contained in:
hneemann 2016-03-24 18:22:03 +01:00
parent 72876b61a9
commit 05e6956d2b
18 changed files with 523 additions and 219 deletions

View File

@ -113,13 +113,6 @@
</key>
<string>Clock</string>
</entry>
<entry>
<key>
<name>Frequency</name>
<def class="int">1</def>
</key>
<int>5</int>
</entry>
</elementAttributes>
<pos x="200" y="170"/>
<rotate>0</rotate>

View File

@ -13,20 +13,6 @@
<pos x="250" y="120"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<key>
<name>Label</name>
<def class="string"></def>
</key>
<string>C</string>
</entry>
</elementAttributes>
<pos x="230" y="130"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>And</elementName>
<elementAttributes>
@ -45,7 +31,7 @@
<elementName>And</elementName>
<elementAttributes>
<entry>
<key reference="../../../../visualElement[4]/elementAttributes/entry/key"/>
<key reference="../../../../visualElement[3]/elementAttributes/entry/key"/>
<int>3</int>
</entry>
</elementAttributes>
@ -68,8 +54,11 @@
<elementName>In</elementName>
<elementAttributes>
<entry>
<key reference="../../../../visualElement[3]/elementAttributes/entry/key"/>
<string>K</string>
<key>
<name>Label</name>
<def class="string"></def>
</key>
<string>J</string>
</entry>
<entry>
<key>
@ -79,21 +68,6 @@
<int>1</int>
</entry>
</elementAttributes>
<pos x="230" y="90"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<key reference="../../../../visualElement[3]/elementAttributes/entry/key"/>
<string>J</string>
</entry>
<entry>
<key reference="../../../../visualElement[8]/elementAttributes/entry[2]/key"/>
<int>1</int>
</entry>
</elementAttributes>
<pos x="230" y="170"/>
<rotate>0</rotate>
</visualElement>
@ -101,7 +75,7 @@
<elementName>Out</elementName>
<elementAttributes>
<entry>
<key reference="../../../../visualElement[3]/elementAttributes/entry/key"/>
<key reference="../../../../visualElement[7]/elementAttributes/entry/key"/>
<string>Q</string>
</entry>
</elementAttributes>
@ -112,7 +86,7 @@
<elementName>Out</elementName>
<elementAttributes>
<entry>
<key reference="../../../../visualElement[3]/elementAttributes/entry/key"/>
<key reference="../../../../visualElement[7]/elementAttributes/entry/key"/>
<string>~Q</string>
</entry>
</elementAttributes>
@ -139,6 +113,31 @@
<pos x="350" y="120"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<key>
<name>Label</name>
<def class="string"></def>
</key>
<string>C</string>
</entry>
</elementAttributes>
<pos x="230" y="130"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<key reference="../../../../visualElement[12]/elementAttributes/entry/key"/>
<string>K</string>
</entry>
</elementAttributes>
<pos x="230" y="90"/>
<rotate>0</rotate>
</visualElement>
</visualElements>
<wires>
<wire>

View File

@ -53,21 +53,6 @@
<pos x="50" y="50"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<key reference="../../../../visualElement[4]/elementAttributes/entry/key"/>
<string>K</string>
</entry>
<entry>
<key reference="../../../../visualElement[4]/elementAttributes/entry[2]/key"/>
<int>1</int>
</entry>
</elementAttributes>
<pos x="50" y="130"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
@ -137,6 +122,20 @@
<pos x="310" y="120"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<key>
<name>Label</name>
<def class="string"></def>
</key>
<string>K</string>
</entry>
</elementAttributes>
<pos x="50" y="130"/>
<rotate>0</rotate>
</visualElement>
</visualElements>
<wires>
<wire>
@ -155,50 +154,10 @@
<p1 x="240" y="100"/>
<p2 x="300" y="80"/>
</wire>
<wire>
<p1 x="70" y="60"/>
<p2 x="80" y="60"/>
</wire>
<wire>
<p1 x="170" y="60"/>
<p2 x="180" y="60"/>
</wire>
<wire>
<p1 x="190" y="60"/>
<p2 x="200" y="60"/>
</wire>
<wire>
<p1 x="290" y="60"/>
<p2 x="300" y="60"/>
</wire>
<wire>
<p1 x="300" y="60"/>
<p2 x="310" y="60"/>
</wire>
<wire>
<p1 x="180" y="140"/>
<p2 x="200" y="140"/>
</wire>
<wire>
<p1 x="70" y="140"/>
<p2 x="80" y="140"/>
</wire>
<wire>
<p1 x="120" y="110"/>
<p2 x="130" y="110"/>
</wire>
<wire>
<p1 x="240" y="110"/>
<p2 x="250" y="110"/>
</wire>
<wire>
<p1 x="70" y="160"/>
<p2 x="240" y="160"/>
</wire>
<wire>
<p1 x="50" y="130"/>
<p2 x="80" y="130"/>
</wire>
<wire>
<p1 x="110" y="130"/>
<p2 x="130" y="130"/>
@ -207,6 +166,10 @@
<p1 x="230" y="130"/>
<p2 x="250" y="130"/>
</wire>
<wire>
<p1 x="50" y="130"/>
<p2 x="80" y="130"/>
</wire>
<wire>
<p1 x="50" y="50"/>
<p2 x="80" y="50"/>
@ -271,6 +234,58 @@
<p1 x="70" y="90"/>
<p2 x="90" y="90"/>
</wire>
<wire>
<p1 x="70" y="60"/>
<p2 x="80" y="60"/>
</wire>
<wire>
<p1 x="170" y="60"/>
<p2 x="180" y="60"/>
</wire>
<wire>
<p1 x="190" y="60"/>
<p2 x="200" y="60"/>
</wire>
<wire>
<p1 x="290" y="60"/>
<p2 x="300" y="60"/>
</wire>
<wire>
<p1 x="300" y="60"/>
<p2 x="310" y="60"/>
</wire>
<wire>
<p1 x="180" y="140"/>
<p2 x="200" y="140"/>
</wire>
<wire>
<p1 x="70" y="140"/>
<p2 x="80" y="140"/>
</wire>
<wire>
<p1 x="120" y="110"/>
<p2 x="130" y="110"/>
</wire>
<wire>
<p1 x="240" y="110"/>
<p2 x="250" y="110"/>
</wire>
<wire>
<p1 x="240" y="20"/>
<p2 x="240" y="70"/>
</wire>
<wire>
<p1 x="240" y="100"/>
<p2 x="240" y="110"/>
</wire>
<wire>
<p1 x="240" y="70"/>
<p2 x="240" y="80"/>
</wire>
<wire>
<p1 x="240" y="110"/>
<p2 x="240" y="160"/>
</wire>
<wire>
<p1 x="180" y="40"/>
<p2 x="180" y="60"/>
@ -279,21 +294,13 @@
<p1 x="180" y="100"/>
<p2 x="180" y="120"/>
</wire>
<wire>
<p1 x="180" y="120"/>
<p2 x="180" y="140"/>
</wire>
<wire>
<p1 x="180" y="60"/>
<p2 x="180" y="80"/>
</wire>
<wire>
<p1 x="300" y="100"/>
<p2 x="300" y="120"/>
</wire>
<wire>
<p1 x="300" y="60"/>
<p2 x="300" y="80"/>
<p1 x="180" y="120"/>
<p2 x="180" y="140"/>
</wire>
<wire>
<p1 x="70" y="60"/>
@ -319,6 +326,14 @@
<p1 x="120" y="70"/>
<p2 x="120" y="80"/>
</wire>
<wire>
<p1 x="300" y="100"/>
<p2 x="300" y="120"/>
</wire>
<wire>
<p1 x="300" y="60"/>
<p2 x="300" y="80"/>
</wire>
<wire>
<p1 x="190" y="60"/>
<p2 x="190" y="90"/>
@ -327,21 +342,5 @@
<p1 x="190" y="90"/>
<p2 x="190" y="120"/>
</wire>
<wire>
<p1 x="240" y="20"/>
<p2 x="240" y="70"/>
</wire>
<wire>
<p1 x="240" y="100"/>
<p2 x="240" y="110"/>
</wire>
<wire>
<p1 x="240" y="110"/>
<p2 x="240" y="160"/>
</wire>
<wire>
<p1 x="240" y="70"/>
<p2 x="240" y="80"/>
</wire>
</wires>
</circuit>

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<circuit>
<visualElements>
<visualElement>
@ -136,25 +137,25 @@
<visualElement>
<elementName>In</elementName>
<elementAttributes/>
<pos x="200" y="230"/>
<pos x="190" y="230"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes/>
<pos x="160" y="240"/>
<pos x="210" y="240"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes/>
<pos x="200" y="250"/>
<pos x="190" y="250"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes/>
<pos x="220" y="260"/>
<pos x="210" y="260"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
@ -169,31 +170,31 @@
<string>1,1,1,1</string>
</entry>
</elementAttributes>
<pos x="320" y="230"/>
<pos x="350" y="230"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes/>
<pos x="370" y="230"/>
<pos x="400" y="230"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes/>
<pos x="390" y="240"/>
<pos x="420" y="240"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes/>
<pos x="370" y="250"/>
<pos x="400" y="250"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes/>
<pos x="390" y="260"/>
<pos x="420" y="260"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
@ -322,13 +323,13 @@
<visualElement>
<elementName>Not</elementName>
<elementAttributes/>
<pos x="350" y="240"/>
<pos x="380" y="240"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
<elementName>Not</elementName>
<elementAttributes/>
<pos x="210" y="240"/>
<pos x="220" y="240"/>
<rotate>0</rotate>
</visualElement>
<visualElement>
@ -433,24 +434,24 @@
<p2 x="370" y="290"/>
</wire>
<wire>
<p1 x="220" y="260"/>
<p1 x="210" y="260"/>
<p2 x="250" y="260"/>
</wire>
<wire>
<p1 x="330" y="260"/>
<p2 x="390" y="260"/>
<p1 x="360" y="260"/>
<p2 x="420" y="260"/>
</wire>
<wire>
<p1 x="200" y="230"/>
<p1 x="190" y="230"/>
<p2 x="250" y="230"/>
</wire>
<wire>
<p1 x="330" y="230"/>
<p2 x="370" y="230"/>
<p1 x="360" y="230"/>
<p2 x="400" y="230"/>
</wire>
<wire>
<p1 x="260" y="230"/>
<p2 x="320" y="230"/>
<p2 x="350" y="230"/>
</wire>
<wire>
<p1 x="260" y="200"/>
@ -493,20 +494,20 @@
<p2 x="300" y="110"/>
</wire>
<wire>
<p1 x="230" y="240"/>
<p1 x="240" y="240"/>
<p2 x="250" y="240"/>
</wire>
<wire>
<p1 x="330" y="240"/>
<p2 x="350" y="240"/>
<p1 x="360" y="240"/>
<p2 x="380" y="240"/>
</wire>
<wire>
<p1 x="370" y="240"/>
<p2 x="390" y="240"/>
<p1 x="400" y="240"/>
<p2 x="420" y="240"/>
</wire>
<wire>
<p1 x="160" y="240"/>
<p2 x="210" y="240"/>
<p1 x="210" y="240"/>
<p2 x="220" y="240"/>
</wire>
<wire>
<p1 x="260" y="180"/>
@ -537,12 +538,12 @@
<p2 x="250" y="120"/>
</wire>
<wire>
<p1 x="200" y="250"/>
<p1 x="190" y="250"/>
<p2 x="250" y="250"/>
</wire>
<wire>
<p1 x="330" y="250"/>
<p2 x="370" y="250"/>
<p1 x="360" y="250"/>
<p2 x="400" y="250"/>
</wire>
<wire>
<p1 x="260" y="190"/>

View File

@ -43,8 +43,8 @@ public abstract class FanIn extends Node implements Element {
addAttributes();
}
public FanInDescription(String name, PartFactory partFactory) {
super(name, partFactory);
public FanInDescription(String name, ElementFactory elementFactory) {
super(name, elementFactory);
addAttributes();
}

View File

@ -3,6 +3,6 @@ package de.neemann.digital.core.element;
/**
* @author hneemann
*/
public interface PartFactory {
public interface ElementFactory {
Element create(ElementAttributes attributes);
}

View File

@ -4,7 +4,7 @@ import java.lang.reflect.Constructor;
import java.util.ArrayList;
/**
* One instance for a element, so there is only one PartDescription for an AND.
* One instance for an element, so there is only one ElementTypeDescription for an AND.
* Regardless of how many of these elements are used in the circuit.
* It has the possibility to create a concrete element by using the given factory
*
@ -13,7 +13,7 @@ import java.util.ArrayList;
public class ElementTypeDescription {
private final String name;
private String shortName;
private final PartFactory partFactory;
private final ElementFactory elementFactory;
private final String[] inputNames;
private final ArrayList<AttributeKey> attributeList;
@ -22,7 +22,7 @@ public class ElementTypeDescription {
}
public ElementTypeDescription(String name, Class<?> clazz, String... inputNames) {
this(name, new PartFactory() {
this(name, new ElementFactory() {
@Override
public Element create(ElementAttributes attributes) {
try {
@ -35,10 +35,10 @@ public class ElementTypeDescription {
}, inputNames);
}
public ElementTypeDescription(String name, PartFactory partFactory, String... inputNames) {
public ElementTypeDescription(String name, ElementFactory elementFactory, String... inputNames) {
this.name = name;
this.shortName = name;
this.partFactory = partFactory;
this.elementFactory = elementFactory;
this.inputNames = inputNames;
attributeList = new ArrayList<>();
}
@ -118,6 +118,6 @@ public class ElementTypeDescription {
* @return the Part instance
*/
public Element createElement(ElementAttributes elementAttributes) {
return partFactory.create(elementAttributes);
return elementFactory.create(elementAttributes);
}
}

View File

@ -1,30 +1,62 @@
package de.neemann.digital.gui;
import de.neemann.digital.core.element.Element;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.ElementFactory;
import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.gui.components.CircuitComponent;
import de.neemann.digital.gui.draw.elements.Circuit;
import de.neemann.digital.gui.draw.elements.VisualElement;
import de.neemann.digital.gui.draw.graphics.Vector;
import de.neemann.digital.gui.draw.library.CustomElement;
import de.neemann.digital.gui.draw.library.ElementLibrary;
import de.neemann.digital.gui.draw.library.ElementNotFoundNotification;
import de.process.utils.gui.ErrorMessage;
import de.process.utils.gui.ToolTipAction;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.File;
/**
* @author hneemann
*/
public class LibrarySelector {
public class LibrarySelector implements ElementNotFoundNotification {
private final ElementLibrary library;
private File lastFile;
private File filePath;
private JMenu customMenu;
private InsertHistory insertHistory;
private CircuitComponent circuitComponent;
public LibrarySelector(ElementLibrary library) {
this.library = library;
library.setElementNotFoundNotification(this);
}
public JMenu buildMenu(InsertHistory insertHistory, CircuitComponent circuitComponent) {
this.insertHistory = insertHistory;
this.circuitComponent = circuitComponent;
JMenu parts = new JMenu("Elements");
customMenu = new JMenu("Custom");
parts.add(customMenu);
ToolTipAction importAction = new ToolTipAction("Import") {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = Main.getjFileChooser(lastFile);
if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
importElement(fc.getSelectedFile());
}
}
}.setToolTip("Imports a model as a useable Element!");
customMenu.add(importAction.createJMenuItem());
JMenu subMenu = null;
String lastPath = null;
for (ElementLibrary.PartContainer pc : library) {
for (ElementLibrary.ElementContainer pc : library) {
String path = pc.getTreePath();
if (!path.equals(lastPath)) {
subMenu = new JMenu(path);
@ -37,6 +69,19 @@ public class LibrarySelector {
return parts;
}
public void setLastFile(File lastFile) {
this.lastFile = lastFile;
}
public void setFilePath(File filePath) {
this.filePath = filePath;
}
@Override
public ElementTypeDescription notFound(String elementName) {
return importElement(new File(filePath, elementName));
}
private class InsertAction extends ToolTipAction {
private final String name;
@ -58,4 +103,22 @@ public class LibrarySelector {
}
}
private ElementTypeDescription importElement(File file) {
try {
Circuit circuit = Circuit.loadCircuit(file);
ElementTypeDescription description = new ElementTypeDescription(file.getName(), new ElementFactory() {
@Override
public Element create(ElementAttributes attributes) {
return new CustomElement(circuit, library);
}
}, circuit.getInputNames(library));
library.addDescription(description);
customMenu.add(new InsertAction(description.getName(), insertHistory, circuitComponent));
return description;
} catch (Exception e) {
new ErrorMessage("error importing model").addCause(e).show();
}
return null;
}
}

View File

@ -1,20 +1,12 @@
package de.neemann.digital.gui;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.StaxDriver;
import de.neemann.digital.core.Model;
import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.Observer;
import de.neemann.digital.core.SpeedTest;
import de.neemann.digital.core.element.AttributeKey;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.gui.components.CircuitComponent;
import de.neemann.digital.gui.draw.elements.Circuit;
import de.neemann.digital.gui.draw.elements.PinException;
import de.neemann.digital.gui.draw.elements.VisualElement;
import de.neemann.digital.gui.draw.elements.Wire;
import de.neemann.digital.gui.draw.graphics.Vector;
import de.neemann.digital.gui.draw.library.ElementLibrary;
import de.neemann.digital.gui.draw.model.ModelDescription;
import de.neemann.digital.gui.draw.shapes.ShapeFactory;
@ -27,7 +19,8 @@ import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.*;
import java.io.File;
import java.io.IOException;
import java.util.prefs.Preferences;
/**
@ -41,6 +34,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
private final ElementLibrary library = ShapeFactory.getInstance().setLibrary(new ElementLibrary());
private final ToolTipAction doStep;
private final JCheckBoxMenuItem traceEnable;
private final LibrarySelector librarySelector;
private File filename;
private Model model;
private ModelDescription modelDescription;
@ -198,7 +192,8 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
toolBar.addSeparator();
bar.add(new LibrarySelector(library).buildMenu(new InsertHistory(toolBar), circuitComponent));
librarySelector = new LibrarySelector(library);
bar.add(librarySelector.buildMenu(new InsertHistory(toolBar), circuitComponent));
getContentPane().add(toolBar, BorderLayout.NORTH);
@ -206,19 +201,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
InfoDialog.getInstance().addToFrame(this, MESSAGE);
}
private static XStream getxStream() {
XStream xStream = new XStream(new StaxDriver());
xStream.alias("visualElement", VisualElement.class);
xStream.alias("wire", Wire.class);
xStream.alias("circuit", Circuit.class);
xStream.alias("vector", Vector.class);
xStream.alias("key", AttributeKey.class);
xStream.addImplicitCollection(ElementAttributes.class, "attributes");
xStream.aliasAttribute(Vector.class, "x", "x");
xStream.aliasAttribute(Vector.class, "y", "y");
return xStream;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new Main().setVisible(true));
}
@ -277,13 +259,14 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
}
private void loadFile(File filename) {
XStream xStream = getxStream();
try (InputStream in = new FileInputStream(filename)) {
Circuit circuit = (Circuit) xStream.fromXML(in);
circuitComponent.setCircuit(circuit);
try {
librarySelector.setFilePath(filename.getParentFile());
Circuit circ = Circuit.loadCircuit(filename);
circuitComponent.setCircuit(circ);
setFilename(filename);
} catch (Exception e) {
new ErrorMessage("error loading file " + filename).addCause(e).show();
circuitComponent.setCircuit(new Circuit());
new ErrorMessage("error reading a file").addCause(e).show(this);
}
}
@ -291,12 +274,9 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
if (!filename.getName().endsWith(".dig"))
filename = new File(filename.getPath() + ".dig");
XStream xStream = getxStream();
try (Writer out = new OutputStreamWriter(new FileOutputStream(filename), "utf-8")) {
out.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
xStream.marshal(circuitComponent.getCircuit(), new PrettyPrintWriter(out));
try {
circuitComponent.getCircuit().save(filename);
setFilename(filename);
circuitComponent.getCircuit().saved();
} catch (IOException e) {
new ErrorMessage("error writing a file").addCause(e).show();
}
@ -304,6 +284,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
private void setFilename(File filename) {
this.filename = filename;
librarySelector.setLastFile(filename);
if (filename != null) {
prefs.put("name", filename.getPath());
setTitle(filename + " - Digital");

View File

@ -327,6 +327,7 @@ public class CircuitComponent extends JComponent implements Observer {
private ArrayList<Moveable> elements;
private Vector lastPos;
private State state;
private Vector copyStartPosition;
private boolean wasRealyDragged;
@Override
@ -352,6 +353,7 @@ public class CircuitComponent extends JComponent implements Observer {
state = State.MOVE;
} else {
elements = circuit.getElementsToCopy(Vector.min(corner1, corner2), Vector.max(corner1, corner2));
copyStartPosition = raster(getPosVector(e));
state = State.COPY;
}
lastPos = getPosVector(e);
@ -360,14 +362,14 @@ public class CircuitComponent extends JComponent implements Observer {
@Override
public void mouseReleased(MouseEvent e) {
if (elements != null && state == State.COPY) {
if (elements != null && state == State.COPY && copyStartPosition != null && !copyStartPosition.equals(raster(getPosVector(e)))) {
for (Moveable m : elements) {
if (m instanceof Wire)
circuit.add((Wire) m);
if (m instanceof VisualElement)
circuit.add((VisualElement) m);
}
reset();
copyStartPosition = null;
}
if (wasRealyDragged)
reset();

View File

@ -1,9 +1,21 @@
package de.neemann.digital.gui.draw.elements;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.StaxDriver;
import de.neemann.digital.core.ObservableValue;
import de.neemann.digital.core.Observer;
import de.neemann.digital.core.element.AttributeKey;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.core.io.In;
import de.neemann.digital.core.io.Out;
import de.neemann.digital.gui.draw.graphics.Graphic;
import de.neemann.digital.gui.draw.graphics.Vector;
import de.neemann.digital.gui.draw.library.ElementLibrary;
import de.neemann.digital.gui.draw.shapes.Drawable;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
@ -16,11 +28,44 @@ public class Circuit implements Drawable {
private transient boolean dotsPresent = false;
private transient boolean modified = false;
private static XStream getxStream() {
XStream xStream = new XStream(new StaxDriver());
xStream.alias("visualElement", VisualElement.class);
xStream.alias("wire", Wire.class);
xStream.alias("circuit", Circuit.class);
xStream.alias("vector", Vector.class);
xStream.alias("key", AttributeKey.class);
xStream.addImplicitCollection(ElementAttributes.class, "attributes");
xStream.aliasAttribute(Vector.class, "x", "x");
xStream.aliasAttribute(Vector.class, "y", "y");
return xStream;
}
public static Circuit loadCircuit(File filename) throws IOException {
XStream xStream = getxStream();
try (InputStream in = new FileInputStream(filename)) {
return (Circuit) xStream.fromXML(in);
}
}
public void save(File filename) throws IOException {
XStream xStream = Circuit.getxStream();
try (Writer out = new OutputStreamWriter(new FileOutputStream(filename), "utf-8")) {
out.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
xStream.marshal(this, new PrettyPrintWriter(out));
modified = false;
}
}
public Circuit() {
visualElements = new ArrayList<>();
wires = new ArrayList<>();
}
@Override
public void drawTo(Graphic graphic) {
if (!dotsPresent) {
@ -148,7 +193,44 @@ public class Circuit implements Drawable {
return modified;
}
public void saved() {
modified = false;
public String[] getInputNames(ElementLibrary library) throws PinException {
ArrayList<String> pinList = new ArrayList<>();
for (VisualElement ve : visualElements) {
ElementTypeDescription elementType = library.getElementType(ve.getElementName());
if (elementType == In.DESCRIPTION) {
String name = ve.getElementAttributes().get(AttributeKey.Label);
if (name == null || name.length() == 0)
throw new PinException("pin without a name!");
pinList.add(name);
}
}
return pinList.toArray(new String[pinList.size()]);
}
public ObservableValue[] getOutputNames(ElementLibrary library) throws PinException {
ArrayList<ObservableValue> pinList = new ArrayList<>();
for (VisualElement ve : visualElements) {
ElementTypeDescription elementType = library.getElementType(ve.getElementName());
if (elementType == Out.DESCRIPTION) {
String name = ve.getElementAttributes().get(AttributeKey.Label);
if (name == null || name.length() == 0)
throw new PinException("pin without a name!");
pinList.add(new ObservableValue(name, 0) {
@Override
public long getValue() {
throw new RuntimeException("invallid call!");
}
@Override
public ObservableValue addObserver(Observer observer) {
throw new RuntimeException("invallid call!");
}
});
}
}
return pinList.toArray(new ObservableValue[pinList.size()]);
}
}

View File

@ -35,7 +35,7 @@ public class Pins implements Iterable<Pin> {
return allPins.iterator();
}
public void setOutputs(ObservableValue[] outs) throws PinException {
public void bindOutputsToOutputPins(ObservableValue[] outs) throws PinException {
for (ObservableValue o : outs) {
Pin pin = outputs.get(o.getName());
if (pin == null)

View File

@ -0,0 +1,46 @@
package de.neemann.digital.gui.draw.library;
import de.neemann.digital.core.Model;
import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.ObservableValue;
import de.neemann.digital.core.element.Element;
import de.neemann.digital.gui.draw.elements.Circuit;
import de.neemann.digital.gui.draw.elements.PinException;
import de.neemann.digital.gui.draw.model.ModelDescription;
/**
* @author hneemann
*/
public class CustomElement implements Element {
private Circuit circuit;
private ElementLibrary library;
public CustomElement(Circuit circuit, ElementLibrary library) {
this.circuit = circuit;
this.library = library;
}
public ModelDescription getModelDescription() throws PinException {
return new ModelDescription(circuit, library, true);
}
@Override
public void setInputs(ObservableValue... inputs) throws NodeException {
throw new RuntimeException("invalid call!");
}
@Override
public ObservableValue[] getOutputs() {
try {
return circuit.getOutputNames(library);
} catch (PinException e) {
throw new RuntimeException(e);
}
}
@Override
public void registerNodes(Model model) {
throw new RuntimeException("invalid call!");
}
}

View File

@ -23,10 +23,11 @@ import java.util.Iterator;
/**
* @author hneemann
*/
public class ElementLibrary implements Iterable<ElementLibrary.PartContainer> {
public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer> {
private final HashMap<String, ElementTypeDescription> map = new HashMap<>();
private ArrayList<PartContainer> list = new ArrayList<>();
private ArrayList<ElementContainer> list = new ArrayList<>();
private ElementNotFoundNotification elementNotFoundNotification;
public ElementLibrary() {
add(And.DESCRIPTION, "Logic");
@ -58,32 +59,47 @@ public class ElementLibrary implements Iterable<ElementLibrary.PartContainer> {
}
private void add(ElementTypeDescription description, String treePath) {
addDescription(description);
list.add(new ElementContainer(description.getName(), treePath));
}
public void addDescription(ElementTypeDescription description) {
String name = description.getName();
if (map.containsKey(name))
throw new RuntimeException("duplicate element " + name);
map.put(name, description);
list.add(new PartContainer(name, treePath));
}
public ElementTypeDescription getElementType(String elementName) {
ElementTypeDescription pd = map.get(elementName);
if (pd == null)
throw new RuntimeException("element " + elementName + " not found");
if (pd == null) {
if (elementNotFoundNotification != null)
pd = elementNotFoundNotification.notFound(elementName);
if (pd == null)
throw new RuntimeException("element " + elementName + " not found");
}
return pd;
}
private ElementTypeDescription loadPart(String elementName) {
return null;
}
@Override
public Iterator<PartContainer> iterator() {
public Iterator<ElementContainer> iterator() {
return list.iterator();
}
public static class PartContainer {
public void setElementNotFoundNotification(ElementNotFoundNotification elementNotFoundNotification) {
this.elementNotFoundNotification = elementNotFoundNotification;
}
public static class ElementContainer {
private final String name;
private final String treePath;
public PartContainer(String name, String treePath) {
public ElementContainer(String name, String treePath) {
this.name = name;
this.treePath = treePath;
}

View File

@ -0,0 +1,10 @@
package de.neemann.digital.gui.draw.library;
import de.neemann.digital.core.element.ElementTypeDescription;
/**
* @author hneemann
*/
public interface ElementNotFoundNotification {
ElementTypeDescription notFound(String elementName);
}

View File

@ -2,9 +2,13 @@ package de.neemann.digital.gui.draw.model;
import de.neemann.digital.core.*;
import de.neemann.digital.core.Observer;
import de.neemann.digital.core.element.AttributeKey;
import de.neemann.digital.core.element.Element;
import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.core.io.In;
import de.neemann.digital.core.io.Out;
import de.neemann.digital.gui.draw.elements.*;
import de.neemann.digital.gui.draw.library.CustomElement;
import de.neemann.digital.gui.draw.library.ElementLibrary;
import java.util.*;
@ -16,44 +20,119 @@ public class ModelDescription implements Iterable<ModelEntry> {
private final NetList netList;
private final ArrayList<ModelEntry> entries;
private final HashMap<String, Pin> ioMap;
private HashMap<Node, ModelEntry> map;
/**
* Creates the ModelDescription.
* After the the NetList is complete, so all pins connected together are registered
* to the Net instances in the NetList. Evenry group of connected Pins is represented
* by a Net-instance in the NetList.
* In created the NetList is complete, so all pins connected together are registered
* to the Net instances in the NetList. Every group of connected Pins is represented
* by a Net instance in the NetList.
*
* @param circuit the circuit
* @param library the library
* @param library the library used to create the Element instances
* @throws PinException
*/
public ModelDescription(Circuit circuit, ElementLibrary library) throws PinException {
this(circuit, library, false);
}
public ModelDescription(Circuit circuit, ElementLibrary library, boolean readAsCustom) throws PinException {
entries = new ArrayList<>();
netList = new NetList(circuit.getWires());
if (readAsCustom)
ioMap = new HashMap<>();
else
ioMap = null;
for (VisualElement vp : circuit.getElements()) {
Pins pins = vp.getPins();
ElementTypeDescription elementType = library.getElementType(vp.getElementName());
Element element = elementType.createElement(vp.getElementAttributes());
pins.setOutputs(element.getOutputs());
pins.bindOutputsToOutputPins(element.getOutputs());
// if handled as nested element, don't put pins in EntryList, but put pin in separate map to connect it with parent!
boolean isNotAIO = true;
if (readAsCustom) {
if (elementType == In.DESCRIPTION || elementType == Out.DESCRIPTION) {
String label = vp.getElementAttributes().get(AttributeKey.Label);
if (label == null || label.length() == 0)
throw new PinException("no pin name given!");
if (pins.size() != 1)
throw new PinException(label + " is not a regular input or output!");
ioMap.put(label, pins.get(0));
isNotAIO = false;
}
}
if (isNotAIO)
entries.add(new ModelEntry(element, pins, vp, elementType.getInputNames(vp.getElementAttributes())));
entries.add(new ModelEntry(element, pins, vp, elementType.getInputNames(vp.getElementAttributes())));
for (Pin p : pins)
netList.add(p);
}
ArrayList<ModelDescription> cmdl = new ArrayList<>();
Iterator<ModelEntry> it = entries.iterator();
while (it.hasNext()) {
ModelEntry me = it.next();
if (me.getElement() instanceof CustomElement) {
CustomElement ce = (CustomElement) me.getElement();
ModelDescription child = ce.getModelDescription();
cmdl.add(child);
for (Pin p : me.getPins()) {
Net childNet = child.getNetOfIOandRemove(p.getName());
Net thisNet = netList.getNetOfPin(p);
// Disconnect the parents net from the pin
thisNet.removePin(p);
// and connect it to the nested inner net!
thisNet.addAll(childNet.getPins());
// remove connecte net form child
child.remove(childNet);
}
it.remove();
}
}
for (ModelDescription md : cmdl) {
entries.addAll(md.entries);
netList.add(md.netList);
}
}
private void remove(Net childNet) {
netList.remove(childNet);
}
private Net getNetOfIOandRemove(String name) throws PinException {
Pin pin = ioMap.get(name);
if (pin == null)
throw new PinException("pin " + name + " not found!");
Net netOfPin = netList.getNetOfPin(pin);
if (netOfPin == null)
throw new PinException("net of pin " + name + " not found!");
netOfPin.removePin(pin);
return netOfPin;
}
/**
* Creates the model
*
* @param bindWiresToValues
* @return the model
* @throws PinException
* @throws NodeException
* @param connectWires
*/
public Model createModel(boolean connectWires) throws PinException, NodeException {
public Model createModel(boolean bindWiresToValues) throws PinException, NodeException {
for (Net n : netList)
n.interconnect(connectWires);
n.interconnect(bindWiresToValues);
Model m = new Model();

View File

@ -7,6 +7,7 @@ import de.neemann.digital.gui.draw.elements.Wire;
import de.neemann.digital.gui.draw.graphics.Vector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
/**
@ -58,7 +59,11 @@ public class Net {
pins.add(pin);
}
public void interconnect(boolean connectWires) throws PinException {
public void addAll(Collection<Pin> p) {
pins.addAll(p);
}
public void interconnect(boolean bindWiresToValues) throws PinException {
ArrayList<Pin> inputs = new ArrayList<>();
ArrayList<Pin> outputs = new ArrayList<>();
for (Pin p : pins) {
@ -81,7 +86,7 @@ public class Net {
for (Pin i : inputs)
i.setValue(value);
if (connectWires)
if (bindWiresToValues)
for (Wire w : wires)
w.setValue(value);
}
@ -97,4 +102,17 @@ public class Net {
return true;
return false;
}
public boolean containsPin(Pin p) {
return pins.contains(p);
}
public ArrayList<Pin> getPins() {
return pins;
}
public void removePin(Pin p) throws PinException {
if (!pins.remove(p))
throw new PinException("pin not present!", this);
}
}

View File

@ -21,6 +21,10 @@ public class NetList implements Iterable<Net> {
add(w);
}
public void add(NetList netList) {
this.netList.addAll(netList.netList);
}
public void add(Pin pin) {
for (Net net : netList)
if (net.contains(pin.getPos()))
@ -58,4 +62,15 @@ public class NetList implements Iterable<Net> {
public Iterator<Net> iterator() {
return netList.iterator();
}
public Net getNetOfPin(Pin p) {
for (Net n : netList)
if (n.containsPin(p))
return n;
return null;
}
public void remove(Net childNet) {
netList.remove(childNet);
}
}